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