1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.plugin.PluginPackage;
28  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.LocaleUtil;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.model.Portlet;
33  import com.liferay.portal.model.PortletCategory;
34  import com.liferay.portal.model.PortletInfo;
35  import com.liferay.portal.model.impl.CompanyImpl;
36  import com.liferay.portal.model.impl.PortletImpl;
37  import com.liferay.portal.service.base.PortletLocalServiceBaseImpl;
38  import com.liferay.portal.util.ContentUtil;
39  import com.liferay.portal.util.PortalUtil;
40  import com.liferay.portal.util.PortletKeys;
41  import com.liferay.portal.util.PropsValues;
42  import com.liferay.portlet.PortletPreferencesSerializer;
43  import com.liferay.util.CollectionFactory;
44  import com.liferay.util.ListUtil;
45  
46  import java.io.IOException;
47  import java.io.StringWriter;
48  
49  import java.util.ArrayList;
50  import java.util.HashMap;
51  import java.util.HashSet;
52  import java.util.Iterator;
53  import java.util.List;
54  import java.util.Map;
55  import java.util.Set;
56  
57  import javax.portlet.PortletMode;
58  import javax.portlet.PreferencesValidator;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  import org.dom4j.Document;
64  import org.dom4j.DocumentException;
65  import org.dom4j.Element;
66  import org.dom4j.io.OutputFormat;
67  import org.dom4j.io.XMLWriter;
68  
69  /**
70   * <a href="PortletLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Brian Wing Shun Chan
73   * @author Raymond Aug?
74   *
75   */
76  public class PortletLocalServiceImpl extends PortletLocalServiceBaseImpl {
77  
78      public void destroyPortlet(Portlet portlet) {
79          Map portletsPool = _getPortletsPool();
80  
81          portletsPool.remove(portlet.getRootPortletId());
82  
83          _clearCaches();
84      }
85  
86      public PortletCategory getEARDisplay(String xml) throws SystemException {
87          try {
88              return _readLiferayDisplayXML(xml);
89          }
90          catch (DocumentException de) {
91              throw new SystemException(de);
92          }
93          catch (IOException ioe) {
94              throw new SystemException(ioe);
95          }
96      }
97  
98      public PortletCategory getWARDisplay(String servletContextName, String xml)
99          throws SystemException {
100 
101         try {
102             return _readLiferayDisplayXML(servletContextName, xml);
103         }
104         catch (DocumentException de) {
105             throw new SystemException(de);
106         }
107         catch (IOException ioe) {
108             throw new SystemException(ioe);
109         }
110     }
111 
112     public List getFriendlyURLMappers() {
113         return _getFriendlyURLMappers();
114     }
115 
116     public Portlet getPortletById(long companyId, String portletId)
117         throws SystemException {
118 
119         portletId = PortalUtil.getJsSafePortletId(portletId);
120 
121         Portlet portlet = null;
122 
123         Map companyPortletsPool = _getPortletsPool(companyId);
124 
125         String rootPortletId = PortletImpl.getRootPortletId(portletId);
126 
127         if (portletId.equals(rootPortletId)) {
128             portlet = (Portlet)companyPortletsPool.get(portletId);
129         }
130         else {
131             portlet = (Portlet)companyPortletsPool.get(rootPortletId);
132 
133             if (portlet != null) {
134                 portlet = portlet.getClonedInstance(portletId);
135             }
136         }
137 
138         if ((portlet == null) &&
139             (!portletId.equals(PortletKeys.LIFERAY_PORTAL))) {
140 
141             if (_log.isWarnEnabled()) {
142                 _log.warn(
143                     "Portlet not found for " + companyId + " " + portletId);
144             }
145         }
146 
147         return portlet;
148     }
149 
150     public Portlet getPortletByStrutsPath(long companyId, String strutsPath)
151         throws SystemException {
152 
153         return getPortletById(companyId, _getPortletId(strutsPath));
154     }
155 
156     public List getPortlets() {
157         Map portletsPool = _getPortletsPool();
158 
159         return ListUtil.fromCollection(portletsPool.values());
160     }
161 
162     public List getPortlets(long companyId) throws SystemException {
163         return getPortlets(companyId, true, true);
164     }
165 
166     public List getPortlets(
167             long companyId, boolean showSystem, boolean showPortal)
168         throws SystemException {
169 
170         Map portletsPool = _getPortletsPool(companyId);
171 
172         List portlets = ListUtil.fromCollection(portletsPool.values());
173 
174         if (!showSystem || !showPortal) {
175             Iterator itr = portlets.iterator();
176 
177             while (itr.hasNext()) {
178                 Portlet portlet = (Portlet)itr.next();
179 
180                 if (showPortal &&
181                     portlet.getPortletId().equals(PortletKeys.PORTAL)) {
182 
183                 }
184                 else if (!showPortal &&
185                          portlet.getPortletId().equals(PortletKeys.PORTAL)) {
186 
187                     itr.remove();
188                 }
189                 else if (!showSystem && portlet.isSystem()) {
190                     itr.remove();
191                 }
192             }
193         }
194 
195         return portlets;
196     }
197 
198     public boolean hasPortlet(long companyId, String portletId)
199         throws SystemException {
200 
201         portletId = PortalUtil.getJsSafePortletId(portletId);
202 
203         Portlet portlet = null;
204 
205         Map companyPortletsPool = _getPortletsPool(companyId);
206 
207         String rootPortletId = PortletImpl.getRootPortletId(portletId);
208 
209         if (portletId.equals(rootPortletId)) {
210             portlet = (Portlet)companyPortletsPool.get(portletId);
211         }
212         else {
213             portlet = (Portlet)companyPortletsPool.get(rootPortletId);
214         }
215 
216         if (portlet == null) {
217             return false;
218         }
219         else {
220             return true;
221         }
222     }
223 
224     public void initEAR(String[] xmls, PluginPackage pluginPackage) {
225         Map portletsPool = _getPortletsPool();
226 
227         try {
228             List servletURLPatterns = _readWebXML(xmls[4]);
229 
230             Set portletIds = _readPortletXML(
231                 xmls[0], portletsPool, servletURLPatterns, pluginPackage);
232 
233             portletIds.addAll(_readPortletXML(
234                 xmls[1], portletsPool, servletURLPatterns, pluginPackage));
235 
236             Set liferayPortletIds =
237                 _readLiferayPortletXML(xmls[2], portletsPool);
238 
239             liferayPortletIds.addAll(
240                 _readLiferayPortletXML(xmls[3], portletsPool));
241 
242             // Check for missing entries in liferay-portlet.xml
243 
244             Iterator itr = portletIds.iterator();
245 
246             while (itr.hasNext()) {
247                 String portletId = (String)itr.next();
248 
249                 if (_log.isWarnEnabled() &&
250                     !liferayPortletIds.contains(portletId)) {
251 
252                     _log.warn(
253                         "Portlet with the name " + portletId +
254                             " is described in portlet.xml but does not " +
255                                 "have a matching entry in liferay-portlet.xml");
256                 }
257             }
258 
259             // Check for missing entries in portlet.xml
260 
261             itr = liferayPortletIds.iterator();
262 
263             while (itr.hasNext()) {
264                 String portletId = (String)itr.next();
265 
266                 if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
267                     _log.warn(
268                         "Portlet with the name " + portletId +
269                             " is described in liferay-portlet.xml but does " +
270                                 "not have a matching entry in portlet.xml");
271                 }
272             }
273 
274             // Remove portlets that should not be included
275 
276             itr = portletsPool.entrySet().iterator();
277 
278             while (itr.hasNext()) {
279                 Map.Entry entry = (Map.Entry)itr.next();
280 
281                 Portlet portletModel = (Portlet)entry.getValue();
282 
283                 if (!portletModel.getPortletId().equals(PortletKeys.ADMIN) &&
284                     !portletModel.getPortletId().equals(
285                         PortletKeys.MY_ACCOUNT) &&
286                     !portletModel.isInclude()) {
287 
288                     itr.remove();
289                 }
290             }
291         }
292         catch (Exception e) {
293             _log.error(e, e);
294         }
295     }
296 
297     public List initWAR(
298         String servletContextName, String[] xmls, PluginPackage pluginPackage) {
299 
300         List portlets = new ArrayList();
301 
302         Map portletsPool = _getPortletsPool();
303 
304         try {
305             List servletURLPatterns = _readWebXML(xmls[3]);
306 
307             Set portletIds = _readPortletXML(
308                 servletContextName, xmls[0], portletsPool, servletURLPatterns,
309                 pluginPackage);
310 
311             portletIds.addAll(_readPortletXML(
312                 servletContextName, xmls[1], portletsPool, servletURLPatterns,
313                 pluginPackage));
314 
315             Set liferayPortletIds = _readLiferayPortletXML(
316                 servletContextName, xmls[2], portletsPool);
317 
318             // Check for missing entries in liferay-portlet.xml
319 
320             Iterator itr = portletIds.iterator();
321 
322             while (itr.hasNext()) {
323                 String portletId = (String)itr.next();
324 
325                 if (_log.isWarnEnabled() &&
326                     !liferayPortletIds.contains(portletId)) {
327 
328                     _log.warn(
329                         "Portlet with the name " + portletId +
330                             " is described in portlet.xml but does not " +
331                                 "have a matching entry in liferay-portlet.xml");
332                 }
333             }
334 
335             // Check for missing entries in portlet.xml
336 
337             itr = liferayPortletIds.iterator();
338 
339             while (itr.hasNext()) {
340                 String portletId = (String)itr.next();
341 
342                 if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
343                     _log.warn(
344                         "Portlet with the name " + portletId +
345                             " is described in liferay-portlet.xml but does " +
346                                 "not have a matching entry in portlet.xml");
347                 }
348             }
349 
350             // Return the new portlets
351 
352             itr = portletIds.iterator();
353 
354             while (itr.hasNext()) {
355                 String portletId = (String)itr.next();
356 
357                 Portlet portlet = (Portlet)_getPortletsPool().get(portletId);
358 
359                 portlets.add(portlet);
360             }
361         }
362         catch (Exception e) {
363             _log.error(e, e);
364         }
365 
366         _clearCaches();
367 
368         return portlets;
369     }
370 
371     public Portlet updatePortlet(
372             long companyId, String portletId, String roles, boolean active)
373         throws PortalException, SystemException {
374 
375         portletId = PortalUtil.getJsSafePortletId(portletId);
376 
377         Portlet portlet = portletPersistence.fetchByC_P(companyId, portletId);
378 
379         if (portlet == null) {
380             long id = counterLocalService.increment();
381 
382             portlet = portletPersistence.create(id);
383 
384             portlet.setCompanyId(companyId);
385             portlet.setPortletId(portletId);
386         }
387 
388         portlet.setRoles(roles);
389         portlet.setActive(active);
390 
391         portletPersistence.update(portlet);
392 
393         portlet = getPortletById(companyId, portletId);
394 
395         portlet.setRoles(roles);
396         portlet.setActive(active);
397 
398         return portlet;
399     }
400 
401     private void _clearCaches() {
402 
403         // Refresh security path to portlet id mapping for all portlets
404 
405         _portletIdsByStrutsPath.clear();
406 
407         // Refresh company portlets
408 
409         _companyPortletsPool.clear();
410     }
411 
412     private List _getFriendlyURLMappers() {
413         List friendlyURLMappers = new ArrayList(
414             _friendlyURLMapperPortlets.size());
415 
416         Iterator itr = _friendlyURLMapperPortlets.entrySet().iterator();
417 
418         while (itr.hasNext()) {
419             Map.Entry entry = (Map.Entry)itr.next();
420 
421             Portlet portlet = (Portlet)entry.getValue();
422 
423             FriendlyURLMapper friendlyURLMapper =
424                 portlet.getFriendlyURLMapperInstance();
425 
426             if (friendlyURLMapper != null) {
427                 friendlyURLMappers.add(friendlyURLMapper);
428             }
429         }
430 
431         return friendlyURLMappers;
432     }
433 
434     private String _getPortletId(String securityPath) throws SystemException {
435         if (_portletIdsByStrutsPath.size() == 0) {
436             Iterator itr = _getPortletsPool().values().iterator();
437 
438             while (itr.hasNext()) {
439                 Portlet portlet = (Portlet)itr.next();
440 
441                 _portletIdsByStrutsPath.put(
442                     portlet.getStrutsPath(), portlet.getPortletId());
443             }
444         }
445 
446         String portletId = (String)_portletIdsByStrutsPath.get(securityPath);
447 
448         if (Validator.isNull(portletId)) {
449             _log.error(
450                 "Struts path " + securityPath + " is not mapped to a portlet " +
451                     "in liferay-portlet.xml");
452         }
453 
454         return portletId;
455     }
456 
457     private Map _getPortletsPool() {
458         return _portletsPool;
459     }
460 
461     private Map _getPortletsPool(long companyId) throws SystemException {
462         Long companyIdObj = new Long(companyId);
463 
464         Map portletsPool = (Map)_companyPortletsPool.get(companyIdObj);
465 
466         if (portletsPool == null) {
467             portletsPool = CollectionFactory.getSyncHashMap();
468 
469             Map parentPortletsPool = _getPortletsPool();
470 
471             if (parentPortletsPool == null) {
472 
473                 // The Upgrade scripts sometimes try to access portlet
474                 // preferences before the portal's been initialized. Return an
475                 // empty pool.
476 
477                 return portletsPool;
478             }
479 
480             Iterator itr = parentPortletsPool.values().iterator();
481 
482             while (itr.hasNext()) {
483                 Portlet portlet = (Portlet)((Portlet)itr.next()).clone();
484 
485                 portlet.setCompanyId(companyId);
486 
487                 portletsPool.put(portlet.getPortletId(), portlet);
488             }
489 
490             itr = portletPersistence.findByCompanyId(companyId).iterator();
491 
492             while (itr.hasNext()) {
493                 Portlet portlet = (Portlet)itr.next();
494 
495                 Portlet portletModel =
496                     (Portlet)portletsPool.get(portlet.getPortletId());
497 
498                 // Portlet may be null if it exists in the database but its
499                 // portlet WAR is not yet loaded
500 
501                 if (portletModel != null) {
502                     portletModel.setPluginPackage(portlet.getPluginPackage());
503                     portletModel.setDefaultPluginSetting(
504                         portlet.getDefaultPluginSetting());
505                     portletModel.setRoles(portlet.getRoles());
506                     portletModel.setActive(portlet.getActive());
507                 }
508             }
509 
510             _companyPortletsPool.put(companyIdObj, portletsPool);
511         }
512 
513         return portletsPool;
514     }
515 
516     private Set _readPortletXML(
517             String xml, Map portletsPool, List servletURLPatterns,
518             PluginPackage pluginPackage)
519         throws DocumentException, IOException {
520 
521         return _readPortletXML(
522             null, xml, portletsPool, servletURLPatterns, pluginPackage);
523     }
524 
525     private Set _readPortletXML(
526             String servletContextName, String xml, Map portletsPool,
527             List servletURLPatterns, PluginPackage pluginPackage)
528         throws DocumentException, IOException {
529 
530         Set portletIds = new HashSet();
531 
532         if (xml == null) {
533             return portletIds;
534         }
535 
536         Document doc = PortalUtil.readDocumentFromXML(xml);
537 
538         Element root = doc.getRootElement();
539 
540         Set userAttributes = new HashSet();
541 
542         Iterator itr1 = root.elements("user-attribute").iterator();
543 
544         while (itr1.hasNext()) {
545             Element userAttribute = (Element)itr1.next();
546 
547             String name = userAttribute.elementText("name");
548 
549             userAttributes.add(name);
550         }
551 
552         itr1 = root.elements("portlet").iterator();
553 
554         while (itr1.hasNext()) {
555             Element portlet = (Element)itr1.next();
556 
557             String portletId = portlet.elementText("portlet-name");
558 
559             if (servletContextName != null) {
560                 portletId =
561                     portletId + PortletImpl.WAR_SEPARATOR + servletContextName;
562             }
563 
564             portletId = PortalUtil.getJsSafePortletId(portletId);
565 
566             if (_log.isDebugEnabled()) {
567                 _log.debug("Reading portlet " + portletId);
568             }
569 
570             portletIds.add(portletId);
571 
572             Portlet portletModel = (Portlet)portletsPool.get(portletId);
573 
574             if (portletModel == null) {
575                 portletModel = new PortletImpl(CompanyImpl.SYSTEM, portletId);
576 
577                 portletsPool.put(portletId, portletModel);
578             }
579 
580             portletModel.setPluginPackage(pluginPackage);
581 
582             if (servletContextName != null) {
583                 portletModel.setServletContextName(servletContextName);
584             }
585 
586             if (servletURLPatterns != null) {
587                 portletModel.setServletURLPatterns(servletURLPatterns);
588             }
589 
590             portletModel.setDisplayName(GetterUtil.getString(
591                 portlet.elementText("display-name"),
592                 portletModel.getDisplayName()));
593             portletModel.setPortletClass(GetterUtil.getString(
594                 portlet.elementText("portlet-class")));
595 
596             Iterator itr2 = portlet.elements("init-param").iterator();
597 
598             while (itr2.hasNext()) {
599                 Element initParam = (Element)itr2.next();
600 
601                 portletModel.getInitParams().put(
602                     initParam.elementText("name"),
603                     initParam.elementText("value"));
604             }
605 
606             Element expirationCache = portlet.element("expiration-cache");
607 
608             if (expirationCache != null) {
609                 portletModel.setExpCache(new Integer(GetterUtil.getInteger(
610                     expirationCache.getText())));
611             }
612 
613             itr2 = portlet.elements("supports").iterator();
614 
615             while (itr2.hasNext()) {
616                 Element supports = (Element)itr2.next();
617 
618                 String mimeType = supports.elementText("mime-type");
619 
620                 Set mimeTypeModes =
621                     (Set)portletModel.getPortletModes().get(mimeType);
622 
623                 if (mimeTypeModes == null) {
624                     mimeTypeModes = new HashSet();
625 
626                     portletModel.getPortletModes().put(mimeType, mimeTypeModes);
627                 }
628 
629                 mimeTypeModes.add(PortletMode.VIEW.toString().toLowerCase());
630 
631                 Iterator itr3 = supports.elements("portlet-mode").iterator();
632 
633                 while (itr3.hasNext()) {
634                     Element portletMode = (Element)itr3.next();
635 
636                     mimeTypeModes.add(portletMode.getTextTrim().toLowerCase());
637                 }
638             }
639 
640             Set supportedLocales = portletModel.getSupportedLocales();
641 
642             supportedLocales.add(
643                 LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
644 
645             itr2 = portlet.elements("supported-locale").iterator();
646 
647             while (itr2.hasNext()) {
648                 Element supportedLocaleEl = (Element)itr2.next();
649 
650                 String supportedLocale = supportedLocaleEl.getText();
651 
652                 supportedLocales.add(supportedLocale);
653             }
654 
655             portletModel.setResourceBundle(
656                 portlet.elementText("resource-bundle"));
657 
658             Element portletInfo = portlet.element("portlet-info");
659 
660             String portletInfoTitle = null;
661             String portletInfoShortTitle = null;
662             String portletInfoKeyWords = null;
663 
664             if (portletInfo != null) {
665                 portletInfoTitle = portletInfo.elementText("title");
666                 portletInfoShortTitle = portletInfo.elementText("short-title");
667                 portletInfoKeyWords = portletInfo.elementText("keywords");
668             }
669 
670             portletModel.setPortletInfo(new PortletInfo(
671                 portletInfoTitle, portletInfoShortTitle, portletInfoKeyWords));
672 
673             Element portletPreferences = portlet.element("portlet-preferences");
674 
675             String defaultPreferences = null;
676             String prefsValidator = null;
677 
678             if (portletPreferences != null) {
679                 Element prefsValidatorEl =
680                     portletPreferences.element("preferences-validator");
681 
682                 if (prefsValidatorEl != null) {
683                     prefsValidator = prefsValidatorEl.getText();
684 
685                     portletPreferences.remove(prefsValidatorEl);
686                 }
687 
688                 StringWriter sw = new StringWriter();
689 
690                 XMLWriter writer = new XMLWriter(
691                     sw, OutputFormat.createCompactFormat());
692 
693                 writer.write(portletPreferences);
694 
695                 defaultPreferences = sw.toString();
696             }
697 
698             portletModel.setDefaultPreferences(defaultPreferences);
699             portletModel.setPreferencesValidator(prefsValidator);
700 
701             if (!portletModel.isWARFile() &&
702                 Validator.isNotNull(prefsValidator) &&
703                 PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
704 
705                 try {
706                     PreferencesValidator prefsValidatorObj =
707                         PortalUtil.getPreferencesValidator(portletModel);
708 
709                     prefsValidatorObj.validate(
710                         PortletPreferencesSerializer.fromDefaultXML(
711                             defaultPreferences));
712                 }
713                 catch (Exception e) {
714                     if (_log.isWarnEnabled()) {
715                         _log.warn(
716                             "Portlet with the name " + portletId +
717                                 " does not have valid default preferences");
718                     }
719                 }
720             }
721 
722             Set unlikedRoles = portletModel.getUnlinkedRoles();
723 
724             itr2 = portlet.elements("security-role-ref").iterator();
725 
726             while (itr2.hasNext()) {
727                 Element role = (Element)itr2.next();
728 
729                 unlikedRoles.add(role.elementText("role-name"));
730             }
731 
732             portletModel.getUserAttributes().addAll(userAttributes);
733         }
734 
735         return portletIds;
736     }
737 
738     private void _readLiferayDisplay(
739         String servletContextName, Element el, PortletCategory portletCategory,
740         Set portletIds) {
741 
742         Iterator itr1 = el.elements("category").iterator();
743 
744         while (itr1.hasNext()) {
745             Element category = (Element)itr1.next();
746 
747             String name = category.attributeValue("name");
748 
749             PortletCategory curPortletCategory = new PortletCategory(name);
750 
751             portletCategory.addCategory(curPortletCategory);
752 
753             Set curPortletIds = curPortletCategory.getPortlets();
754 
755             Iterator itr2 = category.elements("portlet").iterator();
756 
757             while (itr2.hasNext()) {
758                 Element portlet = (Element)itr2.next();
759 
760                 String portletId = portlet.attributeValue("id");
761 
762                 if (servletContextName != null) {
763                     portletId =
764                         portletId + PortletImpl.WAR_SEPARATOR +
765                             servletContextName;
766                 }
767 
768                 portletId = PortalUtil.getJsSafePortletId(portletId);
769 
770                 portletIds.add(portletId);
771                 curPortletIds.add(portletId);
772             }
773 
774             _readLiferayDisplay(
775                 servletContextName, category, curPortletCategory, portletIds);
776         }
777     }
778 
779     private PortletCategory _readLiferayDisplayXML(String xml)
780         throws DocumentException, IOException {
781 
782         return _readLiferayDisplayXML(null, xml);
783     }
784 
785     private PortletCategory _readLiferayDisplayXML(
786             String servletContextName, String xml)
787         throws DocumentException, IOException {
788 
789         PortletCategory portletCategory = new PortletCategory();
790 
791         if (xml == null) {
792             xml = ContentUtil.get(
793                 "com/liferay/portal/deploy/dependencies/liferay-display.xml");
794         }
795 
796         Document doc = PortalUtil.readDocumentFromXML(xml, true);
797 
798         Element root = doc.getRootElement();
799 
800         Set portletIds = new HashSet();
801 
802         _readLiferayDisplay(
803             servletContextName, root, portletCategory, portletIds);
804 
805         // Portlets that do not belong to any categories should default to the
806         // Undefined category
807 
808         Set undefinedPortletIds = new HashSet();
809 
810         Iterator itr = _getPortletsPool().values().iterator();
811 
812         while (itr.hasNext()) {
813             Portlet portlet = (Portlet)itr.next();
814 
815             String portletId = portlet.getPortletId();
816 
817             if ((servletContextName != null) && (portlet.isWARFile()) &&
818                 (portletId.endsWith(
819                     PortletImpl.WAR_SEPARATOR +
820                         PortalUtil.getJsSafePortletId(servletContextName)) &&
821                 (!portletIds.contains(portletId)))) {
822 
823                 undefinedPortletIds.add(portletId);
824             }
825             else if ((servletContextName == null) && (!portlet.isWARFile()) &&
826                      (portletId.indexOf(PortletImpl.WAR_SEPARATOR) == -1) &&
827                      (!portletIds.contains(portletId))) {
828 
829                 undefinedPortletIds.add(portletId);
830             }
831         }
832 
833         if (undefinedPortletIds.size() > 0) {
834             PortletCategory undefinedCategory =
835                 new PortletCategory("category.undefined");
836 
837             portletCategory.addCategory(undefinedCategory);
838 
839             undefinedCategory.getPortlets().addAll(undefinedPortletIds);
840         }
841 
842         return portletCategory;
843     }
844 
845     private Set _readLiferayPortletXML(String xml, Map portletsPool)
846         throws DocumentException, IOException {
847 
848         return _readLiferayPortletXML(null, xml, portletsPool);
849     }
850 
851     private Set _readLiferayPortletXML(
852             String servletContextName, String xml, Map portletsPool)
853         throws DocumentException, IOException {
854 
855         Set liferayPortletIds = new HashSet();
856 
857         if (xml == null) {
858             return liferayPortletIds;
859         }
860 
861         Document doc = PortalUtil.readDocumentFromXML(xml, true);
862 
863         Element root = doc.getRootElement();
864 
865         Map roleMappers = new HashMap();
866 
867         Iterator itr1 = root.elements("role-mapper").iterator();
868 
869         while (itr1.hasNext()) {
870             Element roleMapper = (Element)itr1.next();
871 
872             String roleName = roleMapper.elementText("role-name");
873             String roleLink = roleMapper.elementText("role-link");
874 
875             roleMappers.put(roleName, roleLink);
876         }
877 
878         Map customUserAttributes = new HashMap();
879 
880         itr1 = root.elements("custom-user-attribute").iterator();
881 
882         while (itr1.hasNext()) {
883             Element customUserAttribute = (Element)itr1.next();
884 
885             String customClass = customUserAttribute.elementText(
886                 "custom-class");
887 
888             Iterator itr2 = customUserAttribute.elements("name").iterator();
889 
890             while (itr2.hasNext()) {
891                 Element nameEl = (Element)itr2.next();
892 
893                 String name = nameEl.getText();
894 
895                 customUserAttributes.put(name, customClass);
896             }
897         }
898 
899         itr1 = root.elements("portlet").iterator();
900 
901         while (itr1.hasNext()) {
902             Element portlet = (Element)itr1.next();
903 
904             String portletId = portlet.elementText("portlet-name");
905 
906             if (servletContextName != null) {
907                 portletId =
908                     portletId + PortletImpl.WAR_SEPARATOR + servletContextName;
909             }
910 
911             portletId = PortalUtil.getJsSafePortletId(portletId);
912 
913             if (_log.isDebugEnabled()) {
914                 _log.debug("Reading portlet extension " + portletId);
915             }
916 
917             liferayPortletIds.add(portletId);
918 
919             Portlet portletModel = (Portlet)portletsPool.get(portletId);
920 
921             if (portletModel != null) {
922                 portletModel.setIcon(GetterUtil.getString(
923                     portlet.elementText("icon"), portletModel.getIcon()));
924                 portletModel.setVirtualPath(GetterUtil.getString(
925                     portlet.elementText("virtual-path"),
926                     portletModel.getVirtualPath()));
927                 portletModel.setStrutsPath(GetterUtil.getString(
928                     portlet.elementText("struts-path"),
929                     portletModel.getStrutsPath()));
930 
931                 if (Validator.isNotNull(
932                         portlet.elementText("configuration-path"))) {
933 
934                     _log.error(
935                         "The configuration-path element is no longer " +
936                             "supported. Use configuration-action-class " +
937                                 "instead.");
938                 }
939 
940                 portletModel.setConfigurationActionClass(GetterUtil.getString(
941                     portlet.elementText("configuration-action-class"),
942                     portletModel.getConfigurationActionClass()));
943                 portletModel.setIndexerClass(GetterUtil.getString(
944                     portlet.elementText("indexer-class"),
945                     portletModel.getIndexerClass()));
946                 portletModel.setOpenSearchClass(GetterUtil.getString(
947                     portlet.elementText("open-search-class"),
948                     portletModel.getOpenSearchClass()));
949                 portletModel.setSchedulerClass(GetterUtil.getString(
950                     portlet.elementText("scheduler-class"),
951                     portletModel.getSchedulerClass()));
952                 portletModel.setPortletURLClass(GetterUtil.getString(
953                     portlet.elementText("portlet-url-class"),
954                     portletModel.getPortletURLClass()));
955 
956                 portletModel.setFriendlyURLMapperClass(GetterUtil.getString(
957                     portlet.elementText("friendly-url-mapper-class"),
958                     portletModel.getFriendlyURLMapperClass()));
959 
960                 if (Validator.isNull(
961                         portletModel.getFriendlyURLMapperClass())) {
962 
963                     _friendlyURLMapperPortlets.remove(portletId);
964                 }
965                 else {
966                     _friendlyURLMapperPortlets.put(portletId, portletModel);
967                 }
968 
969                 portletModel.setURLEncoderClass(GetterUtil.getString(
970                     portlet.elementText("url-encoder-class"),
971                     portletModel.getURLEncoderClass()));
972                 portletModel.setPortletDataHandlerClass(GetterUtil.getString(
973                     portlet.elementText("portlet-data-handler-class"),
974                     portletModel.getPortletDataHandlerClass()));
975                 portletModel.setPortletLayoutListenerClass(GetterUtil.getString(
976                     portlet.elementText("portlet-layout-listener-class"),
977                     portletModel.getPortletLayoutListenerClass()));
978                 portletModel.setActivityTrackerInterpreterClass(
979                     GetterUtil.getString(
980                         portlet.elementText(
981                             "activity-tracker-interpreter-class"),
982                             portletModel.getActivityTrackerInterpreterClass()));
983                 portletModel.setPopMessageListenerClass(GetterUtil.getString(
984                     portlet.elementText("pop-message-listener-class"),
985                     portletModel.getPopMessageListenerClass()));
986                 portletModel.setPreferencesCompanyWide(GetterUtil.getBoolean(
987                     portlet.elementText("preferences-company-wide"),
988                     portletModel.isPreferencesCompanyWide()));
989                 portletModel.setPreferencesUniquePerLayout(
990                     GetterUtil.getBoolean(
991                         portlet.elementText("preferences-unique-per-layout"),
992                         portletModel.isPreferencesUniquePerLayout()));
993                 portletModel.setPreferencesOwnedByGroup(GetterUtil.getBoolean(
994                     portlet.elementText("preferences-owned-by-group"),
995                     portletModel.isPreferencesOwnedByGroup()));
996                 portletModel.setUseDefaultTemplate(GetterUtil.getBoolean(
997                     portlet.elementText("use-default-template"),
998                     portletModel.isUseDefaultTemplate()));
999                 portletModel.setShowPortletAccessDenied(GetterUtil.getBoolean(
1000                    portlet.elementText("show-portlet-access-denied"),
1001                    portletModel.isShowPortletAccessDenied()));
1002                portletModel.setShowPortletInactive(GetterUtil.getBoolean(
1003                    portlet.elementText("show-portlet-inactive"),
1004                    portletModel.isShowPortletInactive()));
1005                portletModel.setActionURLRedirect(GetterUtil.getBoolean(
1006                    portlet.elementText("action-url-redirect"),
1007                    portletModel.isActionURLRedirect()));
1008                portletModel.setRestoreCurrentView(GetterUtil.getBoolean(
1009                    portlet.elementText("restore-current-view"),
1010                    portletModel.isRestoreCurrentView()));
1011                portletModel.setMaximizeEdit(GetterUtil.getBoolean(
1012                    portlet.elementText("maximize-edit"),
1013                    portletModel.isMaximizeEdit()));
1014                portletModel.setMaximizeHelp(GetterUtil.getBoolean(
1015                    portlet.elementText("maximize-help"),
1016                    portletModel.isMaximizeHelp()));
1017                portletModel.setPopUpPrint(GetterUtil.getBoolean(
1018                    portlet.elementText("pop-up-print"),
1019                    portletModel.isPopUpPrint()));
1020                portletModel.setLayoutCacheable(GetterUtil.getBoolean(
1021                    portlet.elementText("layout-cacheable"),
1022                    portletModel.isLayoutCacheable()));
1023                portletModel.setInstanceable(GetterUtil.getBoolean(
1024                    portlet.elementText("instanceable"),
1025                    portletModel.isInstanceable()));
1026                portletModel.setUserPrincipalStrategy(GetterUtil.getString(
1027                    portlet.elementText("user-principal-strategy"),
1028                    portletModel.getUserPrincipalStrategy()));
1029                portletModel.setPrivateRequestAttributes(GetterUtil.getBoolean(
1030                    portlet.elementText("private-request-attributes"),
1031                    portletModel.isPrivateRequestAttributes()));
1032                portletModel.setPrivateSessionAttributes(GetterUtil.getBoolean(
1033                    portlet.elementText("private-session-attributes"),
1034                    portletModel.isPrivateSessionAttributes()));
1035                portletModel.setRenderWeight(GetterUtil.getInteger(
1036                    portlet.elementText("render-weight"),
1037                    portletModel.getRenderWeight()));
1038                portletModel.setAjaxable(GetterUtil.getBoolean(
1039                    portlet.elementText("ajaxable"),
1040                    portletModel.isAjaxable()));
1041
1042                List headerPortalCssList = portletModel.getHeaderPortalCss();
1043
1044                Iterator itr2 = portlet.elements(
1045                    "header-portal-css").iterator();
1046
1047                while (itr2.hasNext()) {
1048                    Element headerPortalCssEl = (Element)itr2.next();
1049
1050                    headerPortalCssList.add(headerPortalCssEl.getText());
1051                }
1052
1053                List headerPortletCssList = portletModel.getHeaderPortletCss();
1054
1055                List list = new ArrayList();
1056
1057                list.addAll(portlet.elements("header-css"));
1058                list.addAll(portlet.elements("header-portlet-css"));
1059
1060                itr2 = list.iterator();
1061
1062                while (itr2.hasNext()) {
1063                    Element headerPortletCssEl = (Element)itr2.next();
1064
1065                    headerPortletCssList.add(headerPortletCssEl.getText());
1066                }
1067
1068                List headerPortalJavaScriptList =
1069                    portletModel.getHeaderPortalJavaScript();
1070
1071                itr2 = portlet.elements("header-portal-javascript").iterator();
1072
1073                while (itr2.hasNext()) {
1074                    Element headerPortalJavaScriptEl = (Element)itr2.next();
1075
1076                    headerPortalJavaScriptList.add(
1077                        headerPortalJavaScriptEl.getText());
1078                }
1079
1080                List headerPortletJavaScriptList =
1081                    portletModel.getHeaderPortletJavaScript();
1082
1083                list.clear();
1084
1085                list.addAll(portlet.elements("header-javascript"));
1086                list.addAll(portlet.elements("header-portlet-javascript"));
1087
1088                itr2 = list.iterator();
1089
1090                while (itr2.hasNext()) {
1091                    Element headerPortletJavaScriptEl = (Element)itr2.next();
1092
1093                    headerPortletJavaScriptList.add(
1094                        headerPortletJavaScriptEl.getText());
1095                }
1096
1097                List footerPortalCssList = portletModel.getFooterPortalCss();
1098
1099                itr2 = portlet.elements("footer-portal-css").iterator();
1100
1101                while (itr2.hasNext()) {
1102                    Element footerPortalCssEl = (Element)itr2.next();
1103
1104                    footerPortalCssList.add(footerPortalCssEl.getText());
1105                }
1106
1107                List footerPortletCssList = portletModel.getFooterPortletCss();
1108
1109                itr2 = portlet.elements("footer-portlet-css").iterator();
1110
1111                while (itr2.hasNext()) {
1112                    Element footerPortletCssEl = (Element)itr2.next();
1113
1114                    footerPortletCssList.add(footerPortletCssEl.getText());
1115                }
1116
1117                List footerPortalJavaScriptList =
1118                    portletModel.getFooterPortalJavaScript();
1119
1120                itr2 = portlet.elements("footer-portal-javascript").iterator();
1121
1122                while (itr2.hasNext()) {
1123                    Element footerPortalJavaScriptEl = (Element)itr2.next();
1124
1125                    footerPortalJavaScriptList.add(
1126                        footerPortalJavaScriptEl.getText());
1127                }
1128
1129                List footerPortletJavaScriptList =
1130                    portletModel.getFooterPortletJavaScript();
1131
1132                itr2 = portlet.elements("footer-portlet-javascript").iterator();
1133
1134                while (itr2.hasNext()) {
1135                    Element footerPortletJavaScriptEl = (Element)itr2.next();
1136
1137                    footerPortletJavaScriptList.add(
1138                        footerPortletJavaScriptEl.getText());
1139                }
1140
1141                portletModel.setCssClassWrapper(GetterUtil.getString(
1142                    portlet.elementText("css-class-wrapper"),
1143                    portletModel.getCssClassWrapper()));
1144                portletModel.setAddDefaultResource(GetterUtil.getBoolean(
1145                    portlet.elementText("add-default-resource"),
1146                    portletModel.isAddDefaultResource()));
1147                portletModel.setSystem(GetterUtil.getBoolean(
1148                    portlet.elementText("system"),
1149                    portletModel.isSystem()));
1150                portletModel.setActive(GetterUtil.getBoolean(
1151                    portlet.elementText("active"),
1152                    portletModel.isActive()));
1153                portletModel.setInclude(GetterUtil.getBoolean(
1154                    portlet.elementText("include"),
1155                    portletModel.isInclude()));
1156
1157                if (!portletModel.isAjaxable() &&
1158                    (portletModel.getRenderWeight() < 1)) {
1159
1160                    portletModel.setRenderWeight(1);
1161                }
1162
1163                portletModel.getRoleMappers().putAll(roleMappers);
1164                portletModel.linkRoles();
1165
1166                portletModel.getCustomUserAttributes().putAll(
1167                    customUserAttributes);
1168            }
1169        }
1170
1171        return liferayPortletIds;
1172    }
1173
1174    private List _readWebXML(String xml) throws DocumentException, IOException {
1175        List servletURLPatterns = new ArrayList();
1176
1177        if (xml == null) {
1178            return servletURLPatterns;
1179        }
1180
1181        Document doc = PortalUtil.readDocumentFromXML(xml);
1182
1183        Element root = doc.getRootElement();
1184
1185        Iterator itr = root.elements("servlet-mapping").iterator();
1186
1187        while (itr.hasNext()) {
1188            Element servletMapping = (Element)itr.next();
1189
1190            String urlPattern = servletMapping.elementText("url-pattern");
1191
1192            servletURLPatterns.add(urlPattern);
1193        }
1194
1195        return servletURLPatterns;
1196
1197    }
1198
1199    private static Log _log = LogFactory.getLog(PortletLocalServiceImpl.class);
1200
1201    private static Map _portletsPool = CollectionFactory.getSyncHashMap();
1202    private static Map _companyPortletsPool =
1203        CollectionFactory.getSyncHashMap();
1204    private static Map _portletIdsByStrutsPath =
1205        CollectionFactory.getSyncHashMap();
1206    private static Map _friendlyURLMapperPortlets =
1207        CollectionFactory.getSyncHashMap();
1208
1209}