1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.service.impl;
16  
17  import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
18  import com.liferay.portal.kernel.cache.PortalCache;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.image.SpriteProcessorUtil;
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.plugin.PluginPackage;
25  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
26  import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
27  import com.liferay.portal.kernel.portlet.LiferayWindowState;
28  import com.liferay.portal.kernel.scheduler.SchedulerEntry;
29  import com.liferay.portal.kernel.scheduler.SchedulerEntryImpl;
30  import com.liferay.portal.kernel.scheduler.TimeUnit;
31  import com.liferay.portal.kernel.scheduler.TriggerType;
32  import com.liferay.portal.kernel.servlet.ServletContextUtil;
33  import com.liferay.portal.kernel.util.ContentTypes;
34  import com.liferay.portal.kernel.util.GetterUtil;
35  import com.liferay.portal.kernel.util.ListUtil;
36  import com.liferay.portal.kernel.util.ServerDetector;
37  import com.liferay.portal.kernel.util.StringPool;
38  import com.liferay.portal.kernel.util.Validator;
39  import com.liferay.portal.kernel.xml.Document;
40  import com.liferay.portal.kernel.xml.Element;
41  import com.liferay.portal.kernel.xml.QName;
42  import com.liferay.portal.kernel.xml.SAXReaderUtil;
43  import com.liferay.portal.model.CompanyConstants;
44  import com.liferay.portal.model.EventDefinition;
45  import com.liferay.portal.model.Portlet;
46  import com.liferay.portal.model.PortletApp;
47  import com.liferay.portal.model.PortletCategory;
48  import com.liferay.portal.model.PortletConstants;
49  import com.liferay.portal.model.PortletFilter;
50  import com.liferay.portal.model.PortletInfo;
51  import com.liferay.portal.model.PortletURLListener;
52  import com.liferay.portal.model.PublicRenderParameter;
53  import com.liferay.portal.model.ResourceConstants;
54  import com.liferay.portal.model.Role;
55  import com.liferay.portal.model.impl.EventDefinitionImpl;
56  import com.liferay.portal.model.impl.PortletAppImpl;
57  import com.liferay.portal.model.impl.PortletFilterImpl;
58  import com.liferay.portal.model.impl.PortletImpl;
59  import com.liferay.portal.model.impl.PortletURLListenerImpl;
60  import com.liferay.portal.model.impl.PublicRenderParameterImpl;
61  import com.liferay.portal.security.permission.ActionKeys;
62  import com.liferay.portal.security.permission.ResourceActionsUtil;
63  import com.liferay.portal.service.base.PortletLocalServiceBaseImpl;
64  import com.liferay.portal.util.ContentUtil;
65  import com.liferay.portal.util.PortalUtil;
66  import com.liferay.portal.util.PortletKeys;
67  import com.liferay.portal.util.PropsValues;
68  import com.liferay.portal.util.WebAppPool;
69  import com.liferay.portal.util.WebKeys;
70  import com.liferay.portlet.PortletInstanceFactoryUtil;
71  import com.liferay.portlet.PortletPreferencesSerializer;
72  import com.liferay.portlet.PortletQNameUtil;
73  import com.liferay.portlet.expando.model.CustomAttributesDisplay;
74  import com.liferay.util.bridges.mvc.MVCPortlet;
75  
76  import java.io.File;
77  
78  import java.util.ArrayList;
79  import java.util.HashMap;
80  import java.util.HashSet;
81  import java.util.Iterator;
82  import java.util.LinkedHashSet;
83  import java.util.List;
84  import java.util.Map;
85  import java.util.Properties;
86  import java.util.Set;
87  import java.util.concurrent.ConcurrentHashMap;
88  
89  import javax.portlet.PortletMode;
90  import javax.portlet.PreferencesValidator;
91  import javax.portlet.WindowState;
92  
93  import javax.servlet.ServletContext;
94  
95  /**
96   * <a href="PortletLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
97   *
98   * @author Brian Wing Shun Chan
99   * @author Raymond Augé
100  * @author Eduardo Lundgren
101  * @author Wesley Gong
102  */
103 public class PortletLocalServiceImpl extends PortletLocalServiceBaseImpl {
104 
105     public void checkPortlet(Portlet portlet)
106         throws PortalException, SystemException {
107 
108         if (portlet.isSystem()) {
109             return;
110         }
111 
112         String[] roleNames = portlet.getRolesArray();
113 
114         if (roleNames.length == 0) {
115             return;
116         }
117 
118         long companyId = portlet.getCompanyId();
119         String name = portlet.getPortletId();
120         int scope = ResourceConstants.SCOPE_COMPANY;
121         String primKey = String.valueOf(companyId);
122         String actionId = ActionKeys.ADD_TO_PAGE;
123 
124         List<String> actionIds = ResourceActionsUtil.getPortletResourceActions(
125             name);
126 
127         if (actionIds.contains(actionId)) {
128             for (String roleName : roleNames) {
129                 Role role = roleLocalService.getRole(companyId, roleName);
130 
131                 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
132                     resourcePermissionLocalService.addResourcePermission(
133                         companyId, name, scope, primKey, role.getRoleId(),
134                         actionId);
135                 }
136                 else {
137                     permissionLocalService.setRolePermission(
138                         role.getRoleId(), companyId, name, scope, primKey,
139                         actionId);
140                 }
141             }
142         }
143 
144         updatePortlet(
145             companyId, portlet.getPortletId(), StringPool.BLANK,
146             portlet.isActive());
147     }
148 
149     public void checkPortlets(long companyId)
150         throws PortalException, SystemException {
151 
152         List<Portlet> portlets = getPortlets(companyId);
153 
154         for (Portlet portlet : portlets) {
155             checkPortlet(portlet);
156         }
157     }
158 
159     public void clearCache() {
160 
161         // Refresh security path to portlet id mapping for all portlets
162 
163         _portletIdsByStrutsPath.clear();
164 
165         // Refresh company portlets
166 
167         _companyPortletsPool.removeAll();
168     }
169 
170     public Portlet clonePortlet(long companyId, String portletId)
171         throws SystemException {
172 
173         Portlet portlet = getPortletById(companyId, portletId);
174 
175         return (Portlet)portlet.clone();
176     }
177 
178     public Portlet deployRemotePortlet(Portlet portlet, String categoryName)
179         throws SystemException {
180 
181         Map<String, Portlet> portletsPool = _getPortletsPool();
182 
183         portletsPool.put(portlet.getPortletId(), portlet);
184 
185         clearCache();
186 
187         PortletCategory newPortletCategory = new PortletCategory();
188 
189         PortletCategory oldPortletCategory = new PortletCategory(categoryName);
190 
191         newPortletCategory.addCategory(oldPortletCategory);
192 
193         oldPortletCategory.getPortletIds().add(portlet.getPortletId());
194 
195         long companyId = portlet.getCompanyId();
196 
197         PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
198             String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
199 
200         if (portletCategory != null) {
201             portletCategory.merge(newPortletCategory);
202         }
203         else {
204             _log.error(
205                 "Unable to register remote portlet for company " + companyId +
206                     " because it does not exist");
207         }
208 
209         List<String> portletActions =
210             ResourceActionsUtil.getPortletResourceActions(
211                 portlet.getPortletId());
212 
213         resourceActionLocalService.checkResourceActions(
214             portlet.getPortletId(), portletActions);
215 
216         return portlet;
217     }
218 
219     public void destroyPortlet(Portlet portlet) {
220         Map<String, Portlet> portletsPool = _getPortletsPool();
221 
222         portletsPool.remove(portlet.getRootPortletId());
223 
224         PortletApp portletApp = portlet.getPortletApp();
225 
226         if (portletApp != null) {
227             _portletAppsPool.remove(portletApp.getServletContextName());
228         }
229 
230         clearCache();
231     }
232 
233     public void destroyRemotePortlet(Portlet portlet) {
234         Map<String, Portlet> portletsPool = _getPortletsPool();
235 
236         portletsPool.remove(portlet.getRootPortletId());
237 
238         PortletApp portletApp = portlet.getPortletApp();
239 
240         _portletAppsPool.remove(portletApp.getServletContextName());
241 
242         clearCache();
243     }
244 
245     public List<CustomAttributesDisplay> getCustomAttributesDisplays() {
246         List<CustomAttributesDisplay> customAttributesDisplays =
247             new ArrayList<CustomAttributesDisplay>(
248                 _customAttributesDisplayPortlets.size());
249 
250         for (Map.Entry<String, Portlet> entry :
251                 _customAttributesDisplayPortlets.entrySet()) {
252 
253             Portlet portlet = entry.getValue();
254 
255             List<CustomAttributesDisplay> portletCustomAttributesDisplays =
256                 portlet.getCustomAttributesDisplayInstances();
257 
258             if ((portletCustomAttributesDisplays != null) &&
259                 (!portletCustomAttributesDisplays.isEmpty())) {
260 
261                 customAttributesDisplays.addAll(
262                     portletCustomAttributesDisplays);
263             }
264         }
265 
266         return customAttributesDisplays;
267     }
268 
269     public PortletCategory getEARDisplay(String xml) throws SystemException {
270         try {
271             return _readLiferayDisplayXML(xml);
272         }
273         catch (Exception e) {
274             throw new SystemException(e);
275         }
276     }
277 
278     public List<Portlet> getFriendlyURLMapperPortlets() {
279         List<Portlet> portlets = new ArrayList<Portlet>(
280             _friendlyURLMapperPortlets.size());
281 
282         for (Map.Entry<String, Portlet> entry :
283                 _friendlyURLMapperPortlets.entrySet()) {
284 
285             Portlet portlet = entry.getValue();
286 
287             FriendlyURLMapper friendlyURLMapper =
288                 portlet.getFriendlyURLMapperInstance();
289 
290             if (friendlyURLMapper != null) {
291                 portlets.add(portlet);
292             }
293         }
294 
295         return portlets;
296     }
297 
298     public List<FriendlyURLMapper> getFriendlyURLMappers() {
299         List<FriendlyURLMapper> friendlyURLMappers =
300             new ArrayList<FriendlyURLMapper>(_friendlyURLMapperPortlets.size());
301 
302         for (Map.Entry<String, Portlet> entry :
303                 _friendlyURLMapperPortlets.entrySet()) {
304 
305             Portlet portlet = entry.getValue();
306 
307             FriendlyURLMapper friendlyURLMapper =
308                 portlet.getFriendlyURLMapperInstance();
309 
310             if (friendlyURLMapper != null) {
311                 friendlyURLMappers.add(friendlyURLMapper);
312             }
313         }
314 
315         return friendlyURLMappers;
316     }
317 
318     public PortletApp getPortletApp(String servletContextName) {
319         return _getPortletApp(servletContextName);
320     }
321 
322     public Portlet getPortletById(long companyId, String portletId)
323         throws SystemException {
324 
325         portletId = PortalUtil.getJsSafePortletId(portletId);
326 
327         Portlet portlet = null;
328 
329         Map<String, Portlet> companyPortletsPool = _getPortletsPool(companyId);
330 
331         String rootPortletId = PortletConstants.getRootPortletId(portletId);
332 
333         if (portletId.equals(rootPortletId)) {
334             portlet = companyPortletsPool.get(portletId);
335         }
336         else {
337             portlet = companyPortletsPool.get(rootPortletId);
338 
339             if (portlet != null) {
340                 portlet = portlet.getClonedInstance(portletId);
341             }
342         }
343 
344         if (portlet != null) {
345             return portlet;
346         }
347 
348         if (portletId.equals(PortletKeys.LIFERAY_PORTAL)) {
349             return portlet;
350         }
351 
352         if (_portletsPool.isEmpty()) {
353             if (_log.isDebugEnabled()) {
354                 _log.debug("No portlets are installed");
355             }
356         }
357         else {
358             if (_log.isInfoEnabled()) {
359                 _log.info(
360                     "Portlet not found for " + companyId + " " + portletId);
361             }
362 
363             portlet = new PortletImpl(CompanyConstants.SYSTEM, portletId);
364 
365             portlet.setTimestamp(System.currentTimeMillis());
366 
367             PortletApp portletApp = _getPortletApp(StringPool.BLANK);
368 
369             portlet.setPortletApp(portletApp);
370 
371             portlet.setPortletName(portletId);
372             portlet.setDisplayName(portletId);
373             portlet.setPortletClass(MVCPortlet.class.getName());
374 
375             Map<String, String> initParams = portlet.getInitParams();
376 
377             initParams.put("view-jsp", "/html/portal/undeployed_portlet.jsp");
378 
379             Set<String> mimeTypePortletModes = new HashSet<String>();
380 
381             mimeTypePortletModes.add(PortletMode.VIEW.toString().toLowerCase());
382 
383             portlet.getPortletModes().put(
384                 ContentTypes.TEXT_HTML, mimeTypePortletModes);
385 
386             Set<String> mimeTypeWindowStates = new HashSet<String>();
387 
388             mimeTypeWindowStates.add(
389                 WindowState.NORMAL.toString().toLowerCase());
390 
391             portlet.getWindowStates().put(
392                 ContentTypes.TEXT_HTML, mimeTypeWindowStates);
393 
394             portlet.setPortletInfo(
395                 new PortletInfo(portletId, portletId, portletId, portletId));
396 
397             if (PortletConstants.getInstanceId(portletId) != null) {
398                 portlet.setInstanceable(true);
399             }
400 
401             portlet.setActive(true);
402             portlet.setUndeployedPortlet(true);
403         }
404 
405         return portlet;
406     }
407 
408     public Portlet getPortletById(String portletId) {
409         Map<String, Portlet> portletsPool = _getPortletsPool();
410 
411         return portletsPool.get(portletId);
412     }
413 
414     public Portlet getPortletByStrutsPath(long companyId, String strutsPath)
415         throws SystemException {
416 
417         return getPortletById(companyId, _getPortletId(strutsPath));
418     }
419 
420     public List<Portlet> getPortlets() {
421         Map<String, Portlet> portletsPool = _getPortletsPool();
422 
423         return ListUtil.fromCollection(portletsPool.values());
424     }
425 
426     public List<Portlet> getPortlets(long companyId) throws SystemException {
427         return getPortlets(companyId, true, true);
428     }
429 
430     public List<Portlet> getPortlets(
431             long companyId, boolean showSystem, boolean showPortal)
432         throws SystemException {
433 
434         Map<String, Portlet> portletsPool = _getPortletsPool(companyId);
435 
436         List<Portlet> portlets = ListUtil.fromCollection(portletsPool.values());
437 
438         if (!showSystem || !showPortal) {
439             Iterator<Portlet> itr = portlets.iterator();
440 
441             while (itr.hasNext()) {
442                 Portlet portlet = itr.next();
443 
444                 if (showPortal &&
445                     portlet.getPortletId().equals(PortletKeys.PORTAL)) {
446 
447                 }
448                 else if (!showPortal &&
449                          portlet.getPortletId().equals(PortletKeys.PORTAL)) {
450 
451                     itr.remove();
452                 }
453                 else if (!showSystem && portlet.isSystem()) {
454                     itr.remove();
455                 }
456             }
457         }
458 
459         return portlets;
460     }
461 
462     public PortletCategory getWARDisplay(String servletContextName, String xml)
463         throws SystemException {
464 
465         try {
466             return _readLiferayDisplayXML(servletContextName, xml);
467         }
468         catch (Exception e) {
469             throw new SystemException(e);
470         }
471     }
472 
473     public boolean hasPortlet(long companyId, String portletId)
474         throws SystemException {
475 
476         portletId = PortalUtil.getJsSafePortletId(portletId);
477 
478         Portlet portlet = null;
479 
480         Map<String, Portlet> companyPortletsPool = _getPortletsPool(companyId);
481 
482         String rootPortletId = PortletConstants.getRootPortletId(portletId);
483 
484         if (portletId.equals(rootPortletId)) {
485             portlet = companyPortletsPool.get(portletId);
486         }
487         else {
488             portlet = companyPortletsPool.get(rootPortletId);
489         }
490 
491         if (portlet == null) {
492             return false;
493         }
494         else {
495             return true;
496         }
497     }
498 
499     public void initEAR(
500         ServletContext servletContext, String[] xmls,
501         PluginPackage pluginPackage) {
502 
503         // Clear pools every time initEAR is called. See LEP-5452.
504 
505         _portletAppsPool.clear();
506         _portletsPool.clear();
507         _companyPortletsPool.removeAll();
508         _portletIdsByStrutsPath.clear();
509         _friendlyURLMapperPortlets.clear();
510 
511         Map<String, Portlet> portletsPool = _getPortletsPool();
512 
513         try {
514             Set<String> servletURLPatterns = _readWebXML(xmls[4]);
515 
516             Set<String> portletIds = _readPortletXML(
517                 servletContext, xmls[0], portletsPool, servletURLPatterns,
518                 pluginPackage);
519 
520             portletIds.addAll(
521                 _readPortletXML(
522                     servletContext, xmls[1], portletsPool, servletURLPatterns,
523                     pluginPackage));
524 
525             Set<String> liferayPortletIds =
526                 _readLiferayPortletXML(xmls[2], portletsPool);
527 
528             liferayPortletIds.addAll(
529                 _readLiferayPortletXML(xmls[3], portletsPool));
530 
531             // Check for missing entries in liferay-portlet.xml
532 
533             for (String portletId : portletIds) {
534                 if (_log.isWarnEnabled() &&
535                     !liferayPortletIds.contains(portletId)) {
536 
537                     _log.warn(
538                         "Portlet with the name " + portletId +
539                             " is described in portlet.xml but does not " +
540                                 "have a matching entry in liferay-portlet.xml");
541                 }
542             }
543 
544             // Check for missing entries in portlet.xml
545 
546             for (String portletId : liferayPortletIds) {
547                 if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
548                     _log.warn(
549                         "Portlet with the name " + portletId +
550                             " is described in liferay-portlet.xml but does " +
551                                 "not have a matching entry in portlet.xml");
552                 }
553             }
554 
555             // Remove portlets that should not be included
556 
557             Iterator<Map.Entry<String, Portlet>> portletPoolsItr =
558                 portletsPool.entrySet().iterator();
559 
560             while (portletPoolsItr.hasNext()) {
561                 Map.Entry<String, Portlet> entry = portletPoolsItr.next();
562 
563                 Portlet portletModel = entry.getValue();
564 
565                 if (!portletModel.getPortletId().equals(PortletKeys.ADMIN) &&
566                     !portletModel.getPortletId().equals(
567                         PortletKeys.MY_ACCOUNT) &&
568                     !portletModel.isInclude()) {
569 
570                     portletPoolsItr.remove();
571                 }
572             }
573 
574             // Sprite images
575 
576             PortletApp portletApp = _getPortletApp(StringPool.BLANK);
577 
578             _setSpriteImages(servletContext, portletApp, "/html/icons/");
579         }
580         catch (Exception e) {
581             _log.error(e, e);
582         }
583     }
584 
585     public List<Portlet> initWAR(
586         String servletContextName, ServletContext servletContext, String[] xmls,
587         PluginPackage pluginPackage) {
588 
589         List<Portlet> portlets = new ArrayList<Portlet>();
590 
591         Map<String, Portlet> portletsPool = _getPortletsPool();
592 
593         try {
594             Set<String> servletURLPatterns = _readWebXML(xmls[3]);
595 
596             Set<String> portletIds = _readPortletXML(
597                 servletContextName, servletContext, xmls[0], portletsPool,
598                 servletURLPatterns, pluginPackage);
599 
600             portletIds.addAll(
601                 _readPortletXML(
602                     servletContextName, servletContext, xmls[1], portletsPool,
603                     servletURLPatterns, pluginPackage));
604 
605             Set<String> liferayPortletIds = _readLiferayPortletXML(
606                 servletContextName, xmls[2], portletsPool);
607 
608             // Check for missing entries in liferay-portlet.xml
609 
610             for (String portletId : portletIds) {
611                 if (_log.isWarnEnabled() &&
612                     !liferayPortletIds.contains(portletId)) {
613 
614                     _log.warn(
615                         "Portlet with the name " + portletId +
616                             " is described in portlet.xml but does not " +
617                                 "have a matching entry in liferay-portlet.xml");
618                 }
619             }
620 
621             // Check for missing entries in portlet.xml
622 
623             for (String portletId : liferayPortletIds) {
624                 if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
625                     _log.warn(
626                         "Portlet with the name " + portletId +
627                             " is described in liferay-portlet.xml but does " +
628                                 "not have a matching entry in portlet.xml");
629                 }
630             }
631 
632             // Return the new portlets
633 
634             for (String portletId : portletIds) {
635                 Portlet portlet = _getPortletsPool().get(portletId);
636 
637                 portlets.add(portlet);
638 
639                 PortletInstanceFactoryUtil.clear(portlet);
640             }
641 
642             // Sprite images
643 
644             PortletApp portletApp = _getPortletApp(servletContextName);
645 
646             _setSpriteImages(servletContext, portletApp, "/icons/");
647         }
648         catch (Exception e) {
649             _log.error(e, e);
650         }
651 
652         clearCache();
653 
654         return portlets;
655     }
656 
657     public Portlet updatePortlet(
658             long companyId, String portletId, String roles, boolean active)
659         throws SystemException {
660 
661         portletId = PortalUtil.getJsSafePortletId(portletId);
662 
663         Portlet portlet = portletPersistence.fetchByC_P(companyId, portletId);
664 
665         if (portlet == null) {
666             long id = counterLocalService.increment();
667 
668             portlet = portletPersistence.create(id);
669 
670             portlet.setCompanyId(companyId);
671             portlet.setPortletId(portletId);
672         }
673 
674         portlet.setRoles(roles);
675         portlet.setActive(active);
676 
677         portletPersistence.update(portlet, false);
678 
679         portlet = getPortletById(companyId, portletId);
680 
681         portlet.setRoles(roles);
682         portlet.setActive(active);
683 
684         _updateCompanyPortletsPool(companyId);
685 
686         return portlet;
687     }
688 
689     private String _encodeKey(long companyId) {
690         return _keyPrefix.concat(String.valueOf(companyId));
691     }
692 
693     private PortletApp _getPortletApp(String servletContextName) {
694         PortletApp portletApp = _portletAppsPool.get(servletContextName);
695 
696         if (portletApp == null) {
697             portletApp = new PortletAppImpl(servletContextName);
698 
699             _portletAppsPool.put(servletContextName, portletApp);
700         }
701 
702         return portletApp;
703     }
704 
705     private String _getPortletId(String securityPath) {
706         if (_portletIdsByStrutsPath.size() == 0) {
707             for (Portlet portlet : _getPortletsPool().values()) {
708                 _portletIdsByStrutsPath.put(
709                     portlet.getStrutsPath(), portlet.getPortletId());
710             }
711         }
712 
713         String portletId = _portletIdsByStrutsPath.get(securityPath);
714 
715         if (Validator.isNull(portletId)) {
716             _log.error(
717                 "Struts path " + securityPath + " is not mapped to a portlet " +
718                     "in liferay-portlet.xml");
719         }
720 
721         return portletId;
722     }
723 
724     private List<Portlet> _getPortletsByPortletName(
725         String portletName, String servletContextName,
726         Map<String, Portlet> portletsPool) {
727 
728         List<Portlet> portlets = null;
729 
730         int pos = portletName.indexOf(StringPool.STAR);
731 
732         if (pos == -1) {
733             portlets = new ArrayList<Portlet>();
734 
735             String portletId = portletName;
736 
737             if (Validator.isNotNull(servletContextName)) {
738                 portletId =
739                     portletId + PortletConstants.WAR_SEPARATOR +
740                         servletContextName;
741             }
742 
743             portletId = PortalUtil.getJsSafePortletId(portletId);
744 
745             Portlet portlet = portletsPool.get(portletId);
746 
747             if (portlet != null) {
748                 portlets.add(portlet);
749             }
750 
751             return portlets;
752         }
753 
754         String portletNamePrefix = portletName.substring(0, pos);
755 
756         portlets = _getPortletsByServletContextName(
757             servletContextName, portletsPool);
758 
759         Iterator<Portlet> itr = portlets.iterator();
760 
761         while (itr.hasNext()) {
762             Portlet portlet = itr.next();
763 
764             String portletId = portlet.getPortletId();
765 
766             if (!portletId.startsWith(portletNamePrefix)) {
767                 itr.remove();
768             }
769         }
770 
771         return portlets;
772     }
773 
774     private List<Portlet> _getPortletsByServletContextName(
775         String servletContextName, Map<String, Portlet> portletsPool) {
776 
777         List<Portlet> portlets = new ArrayList<Portlet>();
778 
779         for (Map.Entry<String, Portlet> entry : portletsPool.entrySet()) {
780             String portletId = entry.getKey();
781             Portlet portlet = entry.getValue();
782 
783             if (Validator.isNotNull(servletContextName)) {
784                 if (portletId.endsWith(
785                         PortletConstants.WAR_SEPARATOR + servletContextName)) {
786 
787                     portlets.add(portlet);
788                 }
789             }
790             else {
791                 if (!portletId.contains(PortletConstants.WAR_SEPARATOR)) {
792                     portlets.add(portlet);
793                 }
794             }
795         }
796 
797         return portlets;
798     }
799 
800     private Map<String, Portlet> _getPortletsPool() {
801         return _portletsPool;
802     }
803 
804     private Map<String, Portlet> _getPortletsPool(long companyId)
805         throws SystemException {
806 
807         String key = _encodeKey(companyId);
808 
809         Map<String, Portlet> portletsPool =
810             (Map<String, Portlet>)_companyPortletsPool.get(key);
811 
812         if (portletsPool == null) {
813             portletsPool = new ConcurrentHashMap<String, Portlet>();
814 
815             Map<String, Portlet> parentPortletsPool = _getPortletsPool();
816 
817             if (parentPortletsPool == null) {
818 
819                 // The Upgrade scripts sometimes try to access portlet
820                 // preferences before the portal's been initialized. Return an
821                 // empty pool.
822 
823                 return portletsPool;
824             }
825 
826             for (Portlet portlet : parentPortletsPool.values()) {
827                 portlet = (Portlet)portlet.clone();
828 
829                 portlet.setCompanyId(companyId);
830 
831                 portletsPool.put(portlet.getPortletId(), portlet);
832             }
833 
834             List<Portlet> portlets = portletPersistence.findByCompanyId(
835                 companyId);
836 
837             for (Portlet portlet : portlets) {
838                 Portlet portletModel = portletsPool.get(portlet.getPortletId());
839 
840                 // Portlet may be null if it exists in the database but its
841                 // portlet WAR is not yet loaded
842 
843                 if (portletModel != null) {
844                     portletModel.setPluginPackage(portlet.getPluginPackage());
845                     portletModel.setDefaultPluginSetting(
846                         portlet.getDefaultPluginSetting());
847                     portletModel.setRoles(portlet.getRoles());
848                     portletModel.setActive(portlet.getActive());
849                 }
850             }
851 
852             _companyPortletsPool.put(key, portletsPool);
853         }
854 
855         return portletsPool;
856     }
857 
858     private void _readLiferayDisplay(
859         String servletContextName, Element element,
860         PortletCategory portletCategory, Set<String> portletIds) {
861 
862         for (Element categoryElement : element.elements("category")) {
863             String name = categoryElement.attributeValue("name");
864 
865             PortletCategory curPortletCategory = new PortletCategory(name);
866 
867             portletCategory.addCategory(curPortletCategory);
868 
869             Set<String> curPortletIds = curPortletCategory.getPortletIds();
870 
871             for (Element portletElement : categoryElement.elements("portlet")) {
872                 String portletId = portletElement.attributeValue("id");
873 
874                 if (Validator.isNotNull(servletContextName)) {
875                     portletId =
876                         portletId + PortletConstants.WAR_SEPARATOR +
877                             servletContextName;
878                 }
879 
880                 portletId = PortalUtil.getJsSafePortletId(portletId);
881 
882                 portletIds.add(portletId);
883                 curPortletIds.add(portletId);
884             }
885 
886             _readLiferayDisplay(
887                 servletContextName, categoryElement, curPortletCategory,
888                 portletIds);
889         }
890     }
891 
892     private PortletCategory _readLiferayDisplayXML(String xml)
893         throws Exception {
894 
895         return _readLiferayDisplayXML(null, xml);
896     }
897 
898     private PortletCategory _readLiferayDisplayXML(
899             String servletContextName, String xml)
900         throws Exception {
901 
902         PortletCategory portletCategory = new PortletCategory();
903 
904         if (xml == null) {
905             xml = ContentUtil.get(
906                 "com/liferay/portal/deploy/dependencies/liferay-display.xml");
907         }
908 
909         Document document = SAXReaderUtil.read(xml, true);
910 
911         Element rootElement = document.getRootElement();
912 
913         Set<String> portletIds = new HashSet<String>();
914 
915         _readLiferayDisplay(
916             servletContextName, rootElement, portletCategory, portletIds);
917 
918         // Portlets that do not belong to any categories should default to the
919         // Undefined category
920 
921         Set<String> undefinedPortletIds = new HashSet<String>();
922 
923         for (Portlet portlet : _getPortletsPool().values()) {
924             String portletId = portlet.getPortletId();
925 
926             PortletApp portletApp = portlet.getPortletApp();
927 
928             if ((servletContextName != null) && (portletApp.isWARFile()) &&
929                 (portletId.endsWith(
930                     PortletConstants.WAR_SEPARATOR +
931                         PortalUtil.getJsSafePortletId(servletContextName)) &&
932                 (!portletIds.contains(portletId)))) {
933 
934                 undefinedPortletIds.add(portletId);
935             }
936             else if ((servletContextName == null) &&
937                      (!portletApp.isWARFile()) &&
938                      (portletId.indexOf(
939                         PortletConstants.WAR_SEPARATOR) == -1) &&
940                      (!portletIds.contains(portletId))) {
941 
942                 undefinedPortletIds.add(portletId);
943             }
944         }
945 
946         if (!undefinedPortletIds.isEmpty()) {
947             PortletCategory undefinedCategory = new PortletCategory(
948                 "category.undefined");
949 
950             portletCategory.addCategory(undefinedCategory);
951 
952             undefinedCategory.getPortletIds().addAll(undefinedPortletIds);
953         }
954 
955         return portletCategory;
956     }
957 
958     private Set<String> _readLiferayPortletXML(
959             String xml, Map<String, Portlet> portletsPool)
960         throws Exception {
961 
962         return _readLiferayPortletXML(StringPool.BLANK, xml, portletsPool);
963     }
964 
965     private void _readLiferayPortletXML(
966         String servletContextName, Map<String, Portlet> portletsPool,
967         Set<String> liferayPortletIds, Map<String, String> roleMappers,
968         Element portletElement) {
969 
970         String portletId = portletElement.elementText("portlet-name");
971 
972         if (Validator.isNotNull(servletContextName)) {
973             portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
974                 servletContextName);
975         }
976 
977         portletId = PortalUtil.getJsSafePortletId(portletId);
978 
979         if (_log.isDebugEnabled()) {
980             _log.debug("Reading portlet extension " + portletId);
981         }
982 
983         liferayPortletIds.add(portletId);
984 
985         Portlet portletModel = portletsPool.get(portletId);
986 
987         if (portletModel == null) {
988             return;
989         }
990 
991         portletModel.setIcon(
992             GetterUtil.getString(
993                 portletElement.elementText("icon"), portletModel.getIcon()));
994         portletModel.setVirtualPath(
995             GetterUtil.getString(
996                 portletElement.elementText("virtual-path"),
997                 portletModel.getVirtualPath()));
998         portletModel.setStrutsPath(
999             GetterUtil.getString(
1000                portletElement.elementText("struts-path"),
1001                portletModel.getStrutsPath()));
1002
1003        if (Validator.isNotNull(
1004                portletElement.elementText("configuration-path"))) {
1005
1006            _log.error(
1007                "The configuration-path element is no longer supported. Use " +
1008                    "configuration-action-class instead.");
1009        }
1010
1011        portletModel.setConfigurationActionClass(
1012            GetterUtil.getString(
1013                portletElement.elementText("configuration-action-class"),
1014                portletModel.getConfigurationActionClass()));
1015        portletModel.setIndexerClass(
1016            GetterUtil.getString(
1017                portletElement.elementText("indexer-class"),
1018                portletModel.getIndexerClass()));
1019        portletModel.setOpenSearchClass(
1020            GetterUtil.getString(
1021                portletElement.elementText("open-search-class"),
1022                portletModel.getOpenSearchClass()));
1023
1024        for (Element schedulerEntryElement :
1025                portletElement.elements("scheduler-entry")) {
1026
1027            SchedulerEntry schedulerEntry = new SchedulerEntryImpl();
1028
1029            schedulerEntry.setDescription(
1030                GetterUtil.getString(
1031                    schedulerEntryElement.elementText(
1032                        "scheduler-description")));
1033            schedulerEntry.setEventListenerClass(
1034                GetterUtil.getString(
1035                    schedulerEntryElement.elementText(
1036                        "scheduler-event-listener-class"),
1037                    schedulerEntry.getEventListenerClass()));
1038
1039            Element triggerElement = schedulerEntryElement.element("trigger");
1040
1041            Element cronElement = triggerElement.element("cron");
1042            Element simpleElement = triggerElement.element("simple");
1043
1044            if (cronElement != null) {
1045                schedulerEntry.setTriggerType(TriggerType.CRON);
1046
1047                Element propertyKeyElement = cronElement.element(
1048                    "property-key");
1049
1050                if (propertyKeyElement != null) {
1051                    schedulerEntry.setPropertyKey(
1052                        propertyKeyElement.getTextTrim());
1053                }
1054                else {
1055                    schedulerEntry.setTriggerValue(
1056                        cronElement.elementText("cron-trigger-value"));
1057                }
1058            }
1059            else if (simpleElement != null) {
1060                schedulerEntry.setTriggerType(TriggerType.SIMPLE);
1061
1062                Element propertyKeyElement = simpleElement.element(
1063                    "property-key");
1064
1065                if (propertyKeyElement != null) {
1066                    schedulerEntry.setPropertyKey(
1067                        propertyKeyElement.getTextTrim());
1068                }
1069                else {
1070                    Element simpleTriggerValueElement = simpleElement.element(
1071                        "simple-trigger-value");
1072
1073                    schedulerEntry.setTriggerValue(
1074                        simpleTriggerValueElement.getTextTrim());
1075                }
1076
1077                String timeUnit = GetterUtil.getString(
1078                    simpleElement.elementText("time-unit"),
1079                    TimeUnit.SECOND.getValue());
1080
1081                schedulerEntry.setTimeUnit(
1082                    TimeUnit.parse(timeUnit.toLowerCase()));
1083            }
1084
1085            portletModel.addSchedulerEntry(schedulerEntry);
1086        }
1087
1088        portletModel.setPortletURLClass(
1089            GetterUtil.getString(
1090                portletElement.elementText("portlet-url-class"),
1091                portletModel.getPortletURLClass()));
1092
1093        portletModel.setFriendlyURLMapperClass(
1094            GetterUtil.getString(
1095                portletElement.elementText("friendly-url-mapper-class"),
1096                portletModel.getFriendlyURLMapperClass()));
1097
1098        if (Validator.isNull(portletModel.getFriendlyURLMapperClass())) {
1099            _friendlyURLMapperPortlets.remove(portletId);
1100        }
1101        else {
1102            _friendlyURLMapperPortlets.put(portletId, portletModel);
1103        }
1104
1105        portletModel.setFriendlyURLRoutes(
1106            GetterUtil.getString(
1107                portletElement.elementText("friendly-url-routes"),
1108                portletModel.getFriendlyURLRoutes()));
1109        portletModel.setURLEncoderClass(
1110            GetterUtil.getString(
1111                portletElement.elementText("url-encoder-class"),
1112                portletModel.getURLEncoderClass()));
1113        portletModel.setPortletDataHandlerClass(
1114            GetterUtil.getString(
1115                portletElement.elementText("portlet-data-handler-class"),
1116                portletModel.getPortletDataHandlerClass()));
1117        portletModel.setPortletLayoutListenerClass(
1118            GetterUtil.getString(
1119                portletElement.elementText("portlet-layout-listener-class"),
1120                portletModel.getPortletLayoutListenerClass()));
1121        portletModel.setPollerProcessorClass(
1122            GetterUtil.getString(
1123                portletElement.elementText("poller-processor-class"),
1124                portletModel.getPollerProcessorClass()));
1125        portletModel.setPopMessageListenerClass(
1126            GetterUtil.getString(
1127                portletElement.elementText("pop-message-listener-class"),
1128                portletModel.getPopMessageListenerClass()));
1129        portletModel.setSocialActivityInterpreterClass(
1130            GetterUtil.getString(
1131                portletElement.elementText(
1132                    "social-activity-interpreter-class"),
1133                    portletModel.getSocialActivityInterpreterClass()));
1134        portletModel.setSocialRequestInterpreterClass(
1135            GetterUtil.getString(
1136                portletElement.elementText(
1137                    "social-request-interpreter-class"),
1138                    portletModel.getSocialRequestInterpreterClass()));
1139        portletModel.setWebDAVStorageToken(
1140            GetterUtil.getString(
1141                portletElement.elementText("webdav-storage-token"),
1142                portletModel.getWebDAVStorageToken()));
1143        portletModel.setWebDAVStorageClass(
1144            GetterUtil.getString(
1145                portletElement.elementText("webdav-storage-class"),
1146                portletModel.getWebDAVStorageClass()));
1147        portletModel.setXmlRpcMethodClass(
1148            GetterUtil.getString(
1149                portletElement.elementText("xml-rpc-method-class"),
1150                portletModel.getXmlRpcMethodClass()));
1151        portletModel.setControlPanelEntryCategory(
1152            GetterUtil.getString(
1153                portletElement.elementText("control-panel-entry-category"),
1154                portletModel.getControlPanelEntryCategory()));
1155        portletModel.setControlPanelEntryWeight(
1156            GetterUtil.getDouble(
1157                portletElement.elementText("control-panel-entry-weight"),
1158                portletModel.getControlPanelEntryWeight()));
1159        portletModel.setControlPanelEntryClass(
1160            GetterUtil.getString(
1161                portletElement.elementText("control-panel-entry-class"),
1162                portletModel.getControlPanelEntryClass()));
1163
1164        List<String> assetRendererFactoryClasses =
1165            portletModel.getAssetRendererFactoryClasses();
1166
1167        for (Element assetRendererFactoryClassElement :
1168                portletElement.elements("asset-renderer-factory")) {
1169
1170            assetRendererFactoryClasses.add(
1171                assetRendererFactoryClassElement.getText());
1172        }
1173
1174        List<String> customAttributesDisplayClasses =
1175            portletModel.getCustomAttributesDisplayClasses();
1176
1177        for (Element customAttributesDisplayClassElement :
1178                portletElement.elements("custom-attributes-display")) {
1179
1180            customAttributesDisplayClasses.add(
1181                customAttributesDisplayClassElement.getText());
1182        }
1183
1184        if (customAttributesDisplayClasses.isEmpty()) {
1185            _customAttributesDisplayPortlets.remove(portletId);
1186        }
1187        else {
1188            _customAttributesDisplayPortlets.put(portletId, portletModel);
1189        }
1190
1191        List<String> workflowHandlerClasses =
1192            portletModel.getWorkflowHandlerClasses();
1193
1194        for (Element workflowHandlerClassElement :
1195                portletElement.elements("workflow-handler")) {
1196
1197            workflowHandlerClasses.add(workflowHandlerClassElement.getText());
1198        }
1199
1200        portletModel.setPreferencesCompanyWide(
1201            GetterUtil.getBoolean(
1202                portletElement.elementText("preferences-company-wide"),
1203                portletModel.isPreferencesCompanyWide()));
1204        portletModel.setPreferencesUniquePerLayout(
1205            GetterUtil.getBoolean(
1206                portletElement.elementText("preferences-unique-per-layout"),
1207                portletModel.isPreferencesUniquePerLayout()));
1208        portletModel.setPreferencesOwnedByGroup(
1209            GetterUtil.getBoolean(
1210                portletElement.elementText("preferences-owned-by-group"),
1211                portletModel.isPreferencesOwnedByGroup()));
1212        portletModel.setUseDefaultTemplate(
1213            GetterUtil.getBoolean(
1214                portletElement.elementText("use-default-template"),
1215                portletModel.isUseDefaultTemplate()));
1216        portletModel.setShowPortletAccessDenied(
1217            GetterUtil.getBoolean(
1218                portletElement.elementText("show-portlet-access-denied"),
1219                portletModel.isShowPortletAccessDenied()));
1220        portletModel.setShowPortletInactive(
1221            GetterUtil.getBoolean(
1222                portletElement.elementText("show-portlet-inactive"),
1223                portletModel.isShowPortletInactive()));
1224        portletModel.setActionURLRedirect(
1225            GetterUtil.getBoolean(
1226                portletElement.elementText("action-url-redirect"),
1227                portletModel.isActionURLRedirect()));
1228        portletModel.setRestoreCurrentView(
1229            GetterUtil.getBoolean(
1230                portletElement.elementText("restore-current-view"),
1231                portletModel.isRestoreCurrentView()));
1232        portletModel.setMaximizeEdit(
1233            GetterUtil.getBoolean(
1234                portletElement.elementText("maximize-edit"),
1235                portletModel.isMaximizeEdit()));
1236        portletModel.setMaximizeHelp(
1237            GetterUtil.getBoolean(
1238                portletElement.elementText("maximize-help"),
1239                portletModel.isMaximizeHelp()));
1240        portletModel.setPopUpPrint(
1241            GetterUtil.getBoolean(
1242                portletElement.elementText("pop-up-print"),
1243                portletModel.isPopUpPrint()));
1244        portletModel.setLayoutCacheable(
1245            GetterUtil.getBoolean(
1246                portletElement.elementText("layout-cacheable"),
1247                portletModel.isLayoutCacheable()));
1248        portletModel.setInstanceable(
1249            GetterUtil.getBoolean(
1250                portletElement.elementText("instanceable"),
1251                portletModel.isInstanceable()));
1252        portletModel.setScopeable(
1253            GetterUtil.getBoolean(
1254                portletElement.elementText("scopeable"),
1255                portletModel.isScopeable()));
1256        portletModel.setUserPrincipalStrategy(
1257            GetterUtil.getString(
1258                portletElement.elementText("user-principal-strategy"),
1259                portletModel.getUserPrincipalStrategy()));
1260        portletModel.setPrivateRequestAttributes(
1261            GetterUtil.getBoolean(
1262                portletElement.elementText("private-request-attributes"),
1263                portletModel.isPrivateRequestAttributes()));
1264        portletModel.setPrivateSessionAttributes(
1265            GetterUtil.getBoolean(
1266                portletElement.elementText("private-session-attributes"),
1267                portletModel.isPrivateSessionAttributes()));
1268        portletModel.setRenderWeight(
1269            GetterUtil.getInteger(
1270                portletElement.elementText("render-weight"),
1271                portletModel.getRenderWeight()));
1272        portletModel.setAjaxable(
1273            GetterUtil.getBoolean(
1274                portletElement.elementText("ajaxable"),
1275                portletModel.isAjaxable()));
1276
1277        List<String> headerPortalCssList =
1278            portletModel.getHeaderPortalCss();
1279
1280        for (Element headerPortalCssElement :
1281                portletElement.elements("header-portal-css")) {
1282
1283            headerPortalCssList.add(headerPortalCssElement.getText());
1284        }
1285
1286        List<String> headerPortletCssList = portletModel.getHeaderPortletCss();
1287
1288        for (Element headerPortletCssElement :
1289                portletElement.elements("header-portlet-css")) {
1290
1291            headerPortletCssList.add(headerPortletCssElement.getText());
1292        }
1293
1294        List<String> headerPortalJavaScriptList =
1295            portletModel.getHeaderPortalJavaScript();
1296
1297        for (Element headerPortalJavaScriptElement :
1298                portletElement.elements("header-portal-javascript")) {
1299
1300            headerPortalJavaScriptList.add(
1301                headerPortalJavaScriptElement.getText());
1302        }
1303
1304        List<String> headerPortletJavaScriptList =
1305            portletModel.getHeaderPortletJavaScript();
1306
1307        for (Element headerPortletJavaScriptElement :
1308                portletElement.elements("header-portlet-javascript")) {
1309
1310            headerPortletJavaScriptList.add(
1311                headerPortletJavaScriptElement.getText());
1312        }
1313
1314        List<String> footerPortalCssList = portletModel.getFooterPortalCss();
1315
1316        for (Element footerPortalCssElement :
1317                portletElement.elements("footer-portal-css")) {
1318
1319            footerPortalCssList.add(footerPortalCssElement.getText());
1320        }
1321
1322        List<String> footerPortletCssList = portletModel.getFooterPortletCss();
1323
1324        for (Element footerPortletCssElement :
1325                portletElement.elements("footer-portlet-css")) {
1326
1327            footerPortletCssList.add(footerPortletCssElement.getText());
1328        }
1329
1330        List<String> footerPortalJavaScriptList =
1331            portletModel.getFooterPortalJavaScript();
1332
1333        for (Element footerPortalJavaScriptElement :
1334                portletElement.elements("footer-portal-javascript")) {
1335
1336            footerPortalJavaScriptList.add(
1337                footerPortalJavaScriptElement.getText());
1338        }
1339
1340        List<String> footerPortletJavaScriptList =
1341            portletModel.getFooterPortletJavaScript();
1342
1343        for (Element footerPortletJavaScriptElement :
1344                portletElement.elements("footer-portlet-javascript")) {
1345
1346            footerPortletJavaScriptList.add(
1347                footerPortletJavaScriptElement.getText());
1348        }
1349
1350        portletModel.setCssClassWrapper(GetterUtil.getString(
1351            portletElement.elementText("css-class-wrapper"),
1352            portletModel.getCssClassWrapper()));
1353        portletModel.setFacebookIntegration(GetterUtil.getString(
1354            portletElement.elementText("facebook-integration"),
1355            portletModel.getFacebookIntegration()));
1356        portletModel.setAddDefaultResource(GetterUtil.getBoolean(
1357            portletElement.elementText("add-default-resource"),
1358            portletModel.isAddDefaultResource()));
1359        portletModel.setSystem(GetterUtil.getBoolean(
1360            portletElement.elementText("system"),
1361            portletModel.isSystem()));
1362        portletModel.setActive(GetterUtil.getBoolean(
1363            portletElement.elementText("active"),
1364            portletModel.isActive()));
1365        portletModel.setInclude(GetterUtil.getBoolean(
1366            portletElement.elementText("include"),
1367            portletModel.isInclude()));
1368
1369        if (!portletModel.isAjaxable() &&
1370            (portletModel.getRenderWeight() < 1)) {
1371
1372            portletModel.setRenderWeight(1);
1373        }
1374
1375        portletModel.getRoleMappers().putAll(roleMappers);
1376        portletModel.linkRoles();
1377    }
1378
1379    private Set<String> _readLiferayPortletXML(
1380            String servletContextName, String xml,
1381            Map<String, Portlet> portletsPool)
1382        throws Exception {
1383
1384        Set<String> liferayPortletIds = new HashSet<String>();
1385
1386        if (xml == null) {
1387            return liferayPortletIds;
1388        }
1389
1390        Document document = SAXReaderUtil.read(xml, true);
1391
1392        Element rootElement = document.getRootElement();
1393
1394        PortletApp portletApp = _getPortletApp(servletContextName);
1395
1396        Map<String, String> roleMappers = new HashMap<String, String>();
1397
1398        for (Element roleMapperElement : rootElement.elements("role-mapper")) {
1399            String roleName = roleMapperElement.elementText("role-name");
1400            String roleLink = roleMapperElement.elementText("role-link");
1401
1402            roleMappers.put(roleName, roleLink);
1403        }
1404
1405        Map<String, String> customUserAttributes =
1406            portletApp.getCustomUserAttributes();
1407
1408        for (Element customUserAttributeElement :
1409                rootElement.elements("custom-user-attribute")) {
1410
1411            String customClass = customUserAttributeElement.elementText(
1412                "custom-class");
1413
1414            for (Element nameElement :
1415                    customUserAttributeElement.elements("name")) {
1416
1417                String name = nameElement.getText();
1418
1419                customUserAttributes.put(name, customClass);
1420            }
1421        }
1422
1423        for (Element portletElement : rootElement.elements("portlet")) {
1424            _readLiferayPortletXML(
1425                servletContextName, portletsPool, liferayPortletIds,
1426                roleMappers, portletElement);
1427        }
1428
1429        return liferayPortletIds;
1430    }
1431
1432    private Set<String> _readPortletXML(
1433            ServletContext servletContext, String xml,
1434            Map<String, Portlet> portletsPool, Set<String> servletURLPatterns,
1435            PluginPackage pluginPackage)
1436        throws Exception {
1437
1438        return _readPortletXML(
1439            StringPool.BLANK, servletContext, xml, portletsPool,
1440            servletURLPatterns, pluginPackage);
1441    }
1442
1443    private void _readPortletXML(
1444        String servletContextName, Map<String, Portlet> portletsPool,
1445        PluginPackage pluginPackage, PortletApp portletApp,
1446        Set<String> portletIds, long timestamp, Element portletElement) {
1447
1448        String portletName = portletElement.elementText("portlet-name");
1449
1450        String portletId = portletName;
1451
1452        if (Validator.isNotNull(servletContextName)) {
1453            portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
1454                servletContextName);
1455        }
1456
1457        portletId = PortalUtil.getJsSafePortletId(portletId);
1458
1459        if (_log.isDebugEnabled()) {
1460            _log.debug("Reading portlet " + portletId);
1461        }
1462
1463        portletIds.add(portletId);
1464
1465        Portlet portletModel = portletsPool.get(portletId);
1466
1467        if (portletModel == null) {
1468            portletModel = new PortletImpl(CompanyConstants.SYSTEM, portletId);
1469
1470            portletsPool.put(portletId, portletModel);
1471        }
1472
1473        portletModel.setTimestamp(timestamp);
1474
1475        portletModel.setPluginPackage(pluginPackage);
1476        portletModel.setPortletApp(portletApp);
1477
1478        portletModel.setPortletName(portletName);
1479        portletModel.setDisplayName(
1480            GetterUtil.getString(
1481                portletElement.elementText("display-name"),
1482                portletModel.getDisplayName()));
1483        portletModel.setPortletClass(
1484            GetterUtil.getString(portletElement.elementText("portlet-class")));
1485
1486        Map<String, String> initParams = portletModel.getInitParams();
1487
1488        for (Element initParamElement : portletElement.elements("init-param")) {
1489            initParams.put(
1490                initParamElement.elementText("name"),
1491                initParamElement.elementText("value"));
1492        }
1493
1494        Element expirationCacheElement = portletElement.element(
1495            "expiration-cache");
1496
1497        if (expirationCacheElement != null) {
1498            portletModel.setExpCache(
1499                GetterUtil.getInteger(expirationCacheElement.getText()));
1500        }
1501
1502        for (Element supportsElement : portletElement.elements("supports")) {
1503            Map<String, Set<String>> portletModes =
1504                portletModel.getPortletModes();
1505
1506            String mimeType = supportsElement.elementText("mime-type");
1507
1508            Set<String> mimeTypePortletModes = portletModes.get(mimeType);
1509
1510            if (mimeTypePortletModes == null) {
1511                mimeTypePortletModes = new HashSet<String>();
1512
1513                portletModes.put(mimeType, mimeTypePortletModes);
1514            }
1515
1516            mimeTypePortletModes.add(PortletMode.VIEW.toString().toLowerCase());
1517
1518            for (Element portletModeElement :
1519                    supportsElement.elements("portlet-mode")) {
1520
1521                mimeTypePortletModes.add(
1522                    portletModeElement.getTextTrim().toLowerCase());
1523            }
1524
1525            Map<String, Set<String>> windowStates =
1526                portletModel.getWindowStates();
1527
1528            Set<String> mimeTypeWindowStates = windowStates.get(mimeType);
1529
1530            if (mimeTypeWindowStates == null) {
1531                mimeTypeWindowStates = new HashSet<String>();
1532
1533                windowStates.put(mimeType, mimeTypeWindowStates);
1534            }
1535
1536            mimeTypeWindowStates.add(
1537                WindowState.NORMAL.toString().toLowerCase());
1538
1539            List<Element> windowStateElements = supportsElement.elements(
1540                "window-state");
1541
1542            if (windowStateElements.isEmpty()) {
1543                mimeTypeWindowStates.add(
1544                    WindowState.MAXIMIZED.toString().toLowerCase());
1545                mimeTypeWindowStates.add(
1546                    WindowState.MINIMIZED.toString().toLowerCase());
1547                mimeTypeWindowStates.add(
1548                    LiferayWindowState.EXCLUSIVE.toString().toLowerCase());
1549                mimeTypeWindowStates.add(
1550                    LiferayWindowState.POP_UP.toString().toLowerCase());
1551            }
1552
1553            for (Element windowStateElement : windowStateElements) {
1554                mimeTypeWindowStates.add(
1555                    windowStateElement.getTextTrim().toLowerCase());
1556            }
1557        }
1558
1559        Set<String> supportedLocales = portletModel.getSupportedLocales();
1560
1561        //supportedLocales.add(
1562        //  LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
1563
1564        for (Element supportedLocaleElement : portletElement.elements(
1565                "supported-locale")) {
1566
1567            String supportedLocale = supportedLocaleElement.getText();
1568
1569            supportedLocales.add(supportedLocale);
1570        }
1571
1572        portletModel.setResourceBundle(
1573            portletElement.elementText("resource-bundle"));
1574
1575        Element portletInfoElement = portletElement.element("portlet-info");
1576
1577        String portletInfoTitle = null;
1578        String portletInfoShortTitle = null;
1579        String portletInfoKeyWords = null;
1580        String portletInfoDescription = null;
1581
1582        if (portletInfoElement != null) {
1583            portletInfoTitle = portletInfoElement.elementText("title");
1584            portletInfoShortTitle = portletInfoElement.elementText(
1585                "short-title");
1586            portletInfoKeyWords = portletInfoElement.elementText("keywords");
1587        }
1588
1589        PortletInfo portletInfo = new PortletInfo(
1590            portletInfoTitle, portletInfoShortTitle, portletInfoKeyWords,
1591            portletInfoDescription);
1592
1593        portletModel.setPortletInfo(portletInfo);
1594
1595        Element portletPreferencesElement = portletElement.element(
1596            "portlet-preferences");
1597
1598        String defaultPreferences = null;
1599        String preferencesValidator = null;
1600
1601        if (portletPreferencesElement != null) {
1602            Element preferencesValidatorElement =
1603                portletPreferencesElement.element("preferences-validator");
1604
1605            if (preferencesValidatorElement != null) {
1606                preferencesValidator = preferencesValidatorElement.getText();
1607
1608                portletPreferencesElement.remove(preferencesValidatorElement);
1609            }
1610
1611            defaultPreferences = portletPreferencesElement.asXML();
1612        }
1613
1614        portletModel.setDefaultPreferences(defaultPreferences);
1615        portletModel.setPreferencesValidator(preferencesValidator);
1616
1617        if (!portletApp.isWARFile() &&
1618            Validator.isNotNull(preferencesValidator) &&
1619            PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
1620
1621            try {
1622                PreferencesValidator preferencesValidatorObj =
1623                    PortalUtil.getPreferencesValidator(portletModel);
1624
1625                preferencesValidatorObj.validate(
1626                    PortletPreferencesSerializer.fromDefaultXML(
1627                        defaultPreferences));
1628            }
1629            catch (Exception e) {
1630                if (_log.isWarnEnabled()) {
1631                    _log.warn(
1632                        "Portlet with the name " + portletId +
1633                            " does not have valid default preferences");
1634                }
1635            }
1636        }
1637
1638        Set<String> unlikedRoles = portletModel.getUnlinkedRoles();
1639
1640        for (Element roleElement :
1641                portletElement.elements("security-role-ref")) {
1642
1643            unlikedRoles.add(roleElement.elementText("role-name"));
1644        }
1645
1646        for (Element supportedProcessingEventElement :
1647                portletElement.elements("supported-processing-event")) {
1648
1649            Element qNameElement = supportedProcessingEventElement.element(
1650                "qname");
1651            Element nameElement = supportedProcessingEventElement.element(
1652                "name");
1653
1654            QName qName = PortletQNameUtil.getQName(
1655                qNameElement, nameElement, portletApp.getDefaultNamespace());
1656
1657            portletModel.addProcessingEvent(qName);
1658        }
1659
1660        for (Element supportedPublishingEventElement :
1661                portletElement.elements("supported-publishing-event")) {
1662
1663            Element qNameElement = supportedPublishingEventElement.element(
1664                "qname");
1665            Element nameElement = supportedPublishingEventElement.element(
1666                "name");
1667
1668            QName qName = PortletQNameUtil.getQName(
1669                qNameElement, nameElement, portletApp.getDefaultNamespace());
1670
1671            portletModel.addPublishingEvent(qName);
1672        }
1673
1674        for (Element supportedPublicRenderParameter :
1675                portletElement.elements("supported-public-render-parameter")) {
1676
1677            String identifier = supportedPublicRenderParameter.getTextTrim();
1678
1679            PublicRenderParameter publicRenderParameter =
1680                portletApp.getPublicRenderParameter(identifier);
1681
1682            if (publicRenderParameter == null) {
1683                _log.error(
1684                    "Supported public render parameter references " +
1685                        "unnknown identifier " + identifier);
1686
1687                continue;
1688            }
1689
1690            portletModel.addPublicRenderParameter(publicRenderParameter);
1691        }
1692    }
1693
1694    private Set<String> _readPortletXML(
1695            String servletContextName, ServletContext servletContext,
1696            String xml, Map<String, Portlet> portletsPool,
1697            Set<String> servletURLPatterns, PluginPackage pluginPackage)
1698        throws Exception {
1699
1700        Set<String> portletIds = new HashSet<String>();
1701
1702        if (xml == null) {
1703            return portletIds;
1704        }
1705
1706        Document document = SAXReaderUtil.read(
1707            xml, PropsValues.PORTLET_XML_VALIDATE);
1708
1709        Element rootElement = document.getRootElement();
1710
1711        PortletApp portletApp = _getPortletApp(servletContextName);
1712
1713        portletApp.addServletURLPatterns(servletURLPatterns);
1714
1715        Set<String> userAttributes = portletApp.getUserAttributes();
1716
1717        for (Element userAttributeElement :
1718                rootElement.elements("user-attribute")) {
1719
1720            String name = userAttributeElement.elementText("name");
1721
1722            userAttributes.add(name);
1723        }
1724
1725        String defaultNamespace = rootElement.elementText("default-namespace");
1726
1727        if (Validator.isNotNull(defaultNamespace)) {
1728            portletApp.setDefaultNamespace(defaultNamespace);
1729        }
1730
1731        for (Element eventDefinitionElement :
1732                rootElement.elements("event-definition")) {
1733
1734            Element qNameElement = eventDefinitionElement.element("qname");
1735            Element nameElement = eventDefinitionElement.element("name");
1736            String valueType = eventDefinitionElement.elementText("value-type");
1737
1738            QName qName = PortletQNameUtil.getQName(
1739                qNameElement, nameElement, portletApp.getDefaultNamespace());
1740
1741            EventDefinition eventDefinition = new EventDefinitionImpl(
1742                qName, valueType, portletApp);
1743
1744            portletApp.addEventDefinition(eventDefinition);
1745        }
1746
1747        for (Element publicRenderParameterElement :
1748                rootElement.elements("public-render-parameter")) {
1749
1750            String identifier = publicRenderParameterElement.elementText(
1751                "identifier");
1752            Element qNameElement = publicRenderParameterElement.element(
1753                "qname");
1754            Element nameElement = publicRenderParameterElement.element("name");
1755
1756            QName qName = PortletQNameUtil.getQName(
1757                qNameElement, nameElement, portletApp.getDefaultNamespace());
1758
1759            PublicRenderParameter publicRenderParameter =
1760                new PublicRenderParameterImpl(identifier, qName, portletApp);
1761
1762            portletApp.addPublicRenderParameter(publicRenderParameter);
1763        }
1764
1765        for (Element containerRuntimeOptionElement :
1766                rootElement.elements("container-runtime-option")) {
1767
1768            String name = GetterUtil.getString(
1769                containerRuntimeOptionElement.elementText("name"));
1770
1771            List<String> values = new ArrayList<String>();
1772
1773            for (Element valueElement :
1774                    containerRuntimeOptionElement.elements("value")) {
1775
1776                values.add(valueElement.getTextTrim());
1777            }
1778
1779            Map<String, String[]> containerRuntimeOptions =
1780                portletApp.getContainerRuntimeOptions();
1781
1782            containerRuntimeOptions.put(
1783                name, values.toArray(new String[values.size()]));
1784
1785            if (name.equals(
1786                    LiferayPortletConfig.RUNTIME_OPTION_PORTAL_CONTEXT) &&
1787                !values.isEmpty() && GetterUtil.getBoolean(values.get(0))) {
1788
1789                portletApp.setWARFile(false);
1790            }
1791        }
1792
1793        long timestamp = ServletContextUtil.getLastModified(servletContext);
1794
1795        for (Element portletElement : rootElement.elements("portlet")) {
1796            _readPortletXML(
1797                servletContextName, portletsPool, pluginPackage, portletApp,
1798                portletIds, timestamp, portletElement);
1799        }
1800
1801        for (Element filterElement : rootElement.elements("filter")) {
1802            String filterName = filterElement.elementText("filter-name");
1803            String filterClass = filterElement.elementText("filter-class");
1804
1805            Set<String> lifecycles = new LinkedHashSet<String>();
1806
1807            for (Element lifecycleElement :
1808                    filterElement.elements("lifecycle")) {
1809
1810                lifecycles.add(lifecycleElement.getText());
1811            }
1812
1813            Map<String, String> initParams = new HashMap<String, String>();
1814
1815            for (Element initParamElement :
1816                    filterElement.elements("init-param")) {
1817
1818                initParams.put(
1819                    initParamElement.elementText("name"),
1820                    initParamElement.elementText("value"));
1821            }
1822
1823            PortletFilter portletFilter = new PortletFilterImpl(
1824                filterName, filterClass, lifecycles, initParams, portletApp);
1825
1826            portletApp.addPortletFilter(portletFilter);
1827        }
1828
1829        for (Element filterMappingElement :
1830                rootElement.elements("filter-mapping")) {
1831
1832            String filterName = filterMappingElement.elementText("filter-name");
1833
1834            for (Element portletNameElement :
1835                    filterMappingElement.elements("portlet-name")) {
1836
1837                String portletName = portletNameElement.getTextTrim();
1838
1839                PortletFilter portletFilter = portletApp.getPortletFilter(
1840                    filterName);
1841
1842                if (portletFilter == null) {
1843                    _log.error(
1844                        "Filter mapping references unnknown filter name " +
1845                            filterName);
1846
1847                    continue;
1848                }
1849
1850                List<Portlet> portletModels = _getPortletsByPortletName(
1851                    portletName, servletContextName, portletsPool);
1852
1853                if (portletModels.size() == 0) {
1854                    _log.error(
1855                        "Filter mapping with filter name " + filterName +
1856                            " references unnknown portlet name " + portletName);
1857                }
1858
1859                for (Portlet portletModel : portletModels) {
1860                    portletModel.getPortletFilters().put(
1861                        filterName, portletFilter);
1862                }
1863            }
1864        }
1865
1866        for (Element listenerElement : rootElement.elements("listener")) {
1867            String listenerClass = listenerElement.elementText(
1868                "listener-class");
1869
1870            PortletURLListener portletURLListener = new PortletURLListenerImpl(
1871                listenerClass, portletApp);
1872
1873            portletApp.addPortletURLListener(portletURLListener);
1874        }
1875
1876        return portletIds;
1877    }
1878
1879    private Set<String> _readWebXML(String xml) throws Exception {
1880        Set<String> servletURLPatterns = new LinkedHashSet<String>();
1881
1882        if (xml == null) {
1883            return servletURLPatterns;
1884        }
1885
1886        Document document = SAXReaderUtil.read(xml);
1887
1888        Element rootElement = document.getRootElement();
1889
1890        for (Element servletMappingElement :
1891                rootElement.elements("servlet-mapping")) {
1892
1893            String urlPattern = servletMappingElement.elementText(
1894                "url-pattern");
1895
1896            servletURLPatterns.add(urlPattern);
1897        }
1898
1899        return servletURLPatterns;
1900    }
1901
1902    private void _setSpriteImages(
1903            ServletContext servletContext, PortletApp portletApp,
1904            String resourcePath)
1905        throws Exception {
1906
1907        Set<String> resourcePaths = servletContext.getResourcePaths(
1908            resourcePath);
1909
1910        if (resourcePaths == null) {
1911            return;
1912        }
1913
1914        List<File> images = new ArrayList<File>(resourcePaths.size());
1915
1916        for (String curResourcePath : resourcePaths) {
1917            if (curResourcePath.endsWith(StringPool.SLASH)) {
1918                _setSpriteImages(servletContext, portletApp, curResourcePath);
1919            }
1920            else if (curResourcePath.endsWith(".png")) {
1921                String realPath = ServletContextUtil.getRealPath(
1922                    servletContext, curResourcePath);
1923
1924                if (realPath != null) {
1925                    images.add(new File(realPath));
1926                }
1927                else {
1928                    if (ServerDetector.isTomcat()) {
1929                        if (_log.isInfoEnabled()) {
1930                            _log.info(ServletContextUtil.LOG_INFO_SPRITES);
1931                        }
1932                    }
1933                    else {
1934                        _log.error(
1935                            "Real path for " + curResourcePath + " is null");
1936                    }
1937                }
1938            }
1939        }
1940
1941        String spriteFileName = ".sprite.png";
1942        String spritePropertiesFileName = ".sprite.properties";
1943        String spritePropertiesRootPath = ServletContextUtil.getRealPath(
1944            servletContext, StringPool.SLASH);
1945
1946        Properties spriteProperties = SpriteProcessorUtil.generate(
1947            images, spriteFileName, spritePropertiesFileName,
1948            spritePropertiesRootPath, 16, 16, 10240);
1949
1950        if (spriteProperties == null) {
1951            return;
1952        }
1953
1954        spriteFileName =
1955            resourcePath.substring(0, resourcePath.length()) + spriteFileName;
1956
1957        portletApp.setSpriteImages(spriteFileName, spriteProperties);
1958    }
1959
1960    private void _updateCompanyPortletsPool(long companyId) {
1961        String key = _encodeKey(companyId);
1962
1963        Map<String, Portlet> portletsPool =
1964            (Map<String, Portlet>)_companyPortletsPool.get(key);
1965
1966        _companyPortletsPool.put(key, portletsPool);
1967    }
1968
1969    private static Log _log = LogFactoryUtil.getLog(
1970        PortletLocalServiceImpl.class);
1971
1972    private static PortalCache _companyPortletsPool =
1973        MultiVMPoolUtil.getCache(Portlet.class.getName());
1974    private static Map<String, Portlet> _customAttributesDisplayPortlets =
1975        new ConcurrentHashMap<String, Portlet>();
1976    private static Map<String, Portlet> _friendlyURLMapperPortlets =
1977        new ConcurrentHashMap<String, Portlet>();
1978    private static String _keyPrefix = Portlet.class.getName().concat(
1979        StringPool.POUND);
1980    private static Map<String, PortletApp> _portletAppsPool =
1981        new ConcurrentHashMap<String, PortletApp>();
1982    private static Map<String, String> _portletIdsByStrutsPath =
1983        new ConcurrentHashMap<String, String>();
1984    private static Map<String, Portlet> _portletsPool =
1985        new ConcurrentHashMap<String, Portlet>();
1986
1987}