1   /**
2    * Copyright (c) 2000-2007 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.security.permission;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.language.LanguageUtil;
27  import com.liferay.portal.kernel.security.permission.ActionKeys;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.model.Permission;
31  import com.liferay.portal.model.Portlet;
32  import com.liferay.portal.model.impl.PortletImpl;
33  import com.liferay.portal.service.PortletLocalServiceUtil;
34  import com.liferay.portal.util.PortalUtil;
35  import com.liferay.portal.util.PortletKeys;
36  import com.liferay.portal.util.PropsUtil;
37  import com.liferay.portlet.PortletResourceBundles;
38  import com.liferay.util.CollectionFactory;
39  import com.liferay.util.UniqueList;
40  
41  import java.io.StringReader;
42  
43  import java.util.ArrayList;
44  import java.util.Collections;
45  import java.util.HashSet;
46  import java.util.Iterator;
47  import java.util.List;
48  import java.util.Locale;
49  import java.util.Map;
50  import java.util.Set;
51  
52  import javax.servlet.jsp.PageContext;
53  
54  import org.apache.commons.logging.Log;
55  import org.apache.commons.logging.LogFactory;
56  
57  import org.dom4j.Document;
58  import org.dom4j.Element;
59  import org.dom4j.io.SAXReader;
60  
61  /**
62   * <a href="ResourceActionsUtil.java.html"><b><i>View Source</i></b></a>
63   *
64   * @author Brian Wing Shun Chan
65   *
66   */
67  public class ResourceActionsUtil {
68  
69      public static final String ACTION_NAME_PREFIX = "action.";
70  
71      public static final String MODEL_RESOURCE_NAME_PREFIX = "model.resource.";
72  
73      public static String getAction(
74          long companyId, Locale locale, String action) {
75  
76          String key = ACTION_NAME_PREFIX + action;
77  
78          String value = LanguageUtil.get(companyId, locale, key, null);
79  
80          if ((value == null) || (value.equals(key))) {
81              value = PortletResourceBundles.getString(locale, key);
82          }
83  
84          if (value == null) {
85              value = key;
86          }
87  
88          return value;
89      }
90  
91      public static String getAction(PageContext pageContext, String action) {
92          String key = ACTION_NAME_PREFIX + action;
93  
94          String value = LanguageUtil.get(pageContext, key, null);
95  
96          if ((value == null) || (value.equals(key))) {
97              value = PortletResourceBundles.getString(pageContext, key);
98          }
99  
100         if (value == null) {
101             value = key;
102         }
103 
104         return value;
105     }
106 
107     public static List getActions(List permissions) {
108         List actions = new UniqueList();
109 
110         Iterator itr = permissions.iterator();
111 
112         while (itr.hasNext()) {
113             Permission permission = (Permission)itr.next();
114 
115             actions.add(permission.getActionId());
116         }
117 
118         return actions;
119     }
120 
121     public static List getActionsNames(PageContext pageContext, List actions) {
122         List uniqueList = new UniqueList();
123 
124         Iterator itr = actions.iterator();
125 
126         while (itr.hasNext()) {
127             String action = (String)itr.next();
128 
129             uniqueList.add(getAction(pageContext, action));
130         }
131 
132         List list = new ArrayList();
133 
134         list.addAll(uniqueList);
135 
136         Collections.sort(list);
137 
138         return list;
139     }
140 
141     public static List getModelPortletResources(String name) {
142         return _instance._getModelPortletResources(name);
143     }
144 
145     public static String getModelResource(
146         long companyId, Locale locale, String name) {
147 
148         String key = MODEL_RESOURCE_NAME_PREFIX + name;
149 
150         String value = LanguageUtil.get(companyId, locale, key, null);
151 
152         if ((value == null) || (value.equals(key))) {
153             value = PortletResourceBundles.getString(locale, key);
154         }
155 
156         if (value == null) {
157             value = key;
158         }
159 
160         return value;
161     }
162 
163     public static String getModelResource(
164         PageContext pageContext, String name) {
165 
166         String key = MODEL_RESOURCE_NAME_PREFIX + name;
167 
168         String value = LanguageUtil.get(pageContext, key, null);
169 
170         if ((value == null) || (value.equals(key))) {
171             value = PortletResourceBundles.getString(pageContext, key);
172         }
173 
174         if (value == null) {
175             value = key;
176         }
177 
178         return value;
179     }
180 
181     public static List getModelResourceActions(String name) {
182         return _instance._getModelResourceActions(name);
183     }
184 
185     public static List getModelResourceCommunityDefaultActions(String name) {
186         return _instance._getModelResourceCommunityDefaultActions(name);
187     }
188 
189     public static List getModelResourceGuestDefaultActions(String name) {
190         return _instance._getModelResourceGuestDefaultActions(name);
191     }
192 
193     public static List getModelResourceGuestUnsupportedActions(String name) {
194         return _instance._getModelResourceGuestUnsupportedActions(name);
195     }
196 
197     public static List getPortletModelResources(String portletName) {
198         return _instance._getPortletModelResources(portletName);
199     }
200 
201     public static List getPortletResourceActions(long companyId, String name)
202         throws SystemException {
203 
204         return _instance._getPortletResourceActions(companyId, name);
205     }
206 
207     public static List getPortletResourceCommunityDefaultActions(String name)
208         throws SystemException {
209 
210         return _instance._getPortletResourceCommunityDefaultActions(name);
211     }
212 
213     public static List getPortletResourceGuestDefaultActions(String name)
214         throws SystemException {
215 
216         return _instance._getPortletResourceGuestDefaultActions(name);
217     }
218 
219     public static List getPortletResourceGuestUnsupportedActions(String name)
220         throws SystemException {
221 
222         return _instance._getPortletResourceGuestUnsupportedActions(name);
223     }
224 
225     public static List getResourceActions(
226             long companyId, String portletResource, String modelResource)
227         throws SystemException {
228 
229         List actions = null;
230 
231         if (Validator.isNull(modelResource)) {
232             actions = getPortletResourceActions(companyId, portletResource);
233         }
234         else {
235             actions = getModelResourceActions(modelResource);
236         }
237 
238         return actions;
239     }
240 
241     public static List getResourceGuestUnsupportedActions(
242             String portletResource, String modelResource)
243         throws SystemException {
244 
245         List actions = null;
246 
247         if (Validator.isNull(modelResource)) {
248             actions =
249                 getPortletResourceGuestUnsupportedActions(portletResource);
250         }
251         else {
252             actions = getModelResourceGuestUnsupportedActions(modelResource);
253         }
254 
255         return actions;
256     }
257 
258     public static void read(
259             String servletContextName, ClassLoader classLoader, String source)
260         throws Exception {
261 
262         _instance._read(servletContextName, classLoader, source);
263     }
264 
265     private ResourceActionsUtil() {
266         _portletModelResources = CollectionFactory.getHashMap();
267         _portletResourceActions = CollectionFactory.getHashMap();
268         _portletResourceCommunityDefaultActions =
269             CollectionFactory.getHashMap();
270         _portletResourceGuestDefaultActions = CollectionFactory.getHashMap();
271         _portletResourceGuestUnsupportedActions =
272             CollectionFactory.getHashMap();
273         _modelPortletResources = CollectionFactory.getHashMap();
274         _modelResourceActions = CollectionFactory.getHashMap();
275         _modelResourceCommunityDefaultActions = CollectionFactory.getHashMap();
276         _modelResourceGuestDefaultActions = CollectionFactory.getHashMap();
277         _modelResourceGuestUnsupportedActions = CollectionFactory.getHashMap();
278 
279         try {
280             ClassLoader classLoader = getClass().getClassLoader();
281 
282             String[] configs = StringUtil.split(
283                 PropsUtil.get(PropsUtil.RESOURCE_ACTIONS_CONFIGS));
284 
285             for (int i = 0; i < configs.length; i++) {
286                 _read(null, classLoader, configs[i]);
287             }
288         }
289         catch (Exception e) {
290             _log.error(e, e);
291         }
292     }
293 
294     private void _checkGuestUnsupportedActions(
295         List guestUnsupportedActions, List guestDefaultActions) {
296 
297         // Guest default actions cannot reference guest unsupported actions
298 
299         Iterator itr = guestDefaultActions.iterator();
300 
301         while (itr.hasNext()) {
302             String actionId = (String)itr.next();
303 
304             if (guestUnsupportedActions.contains(actionId)) {
305                 itr.remove();
306             }
307         }
308     }
309 
310     private void _checkPortletActions(List actions) {
311         if (!actions.contains("CONFIGURATION")) {
312             actions.add("CONFIGURATION");
313         }
314 
315         if (!actions.contains("VIEW")) {
316             actions.add("VIEW");
317         }
318     }
319 
320     private void _checkPortletCommunityDefaultActions(List actions) {
321         if (actions.size() == 0) {
322             actions.add("VIEW");
323         }
324     }
325 
326     private void _checkPortletGuestDefaultActions(List actions) {
327         if (actions.size() == 0) {
328             actions.add("VIEW");
329         }
330     }
331 
332     private List _getActions(Map map, String name) {
333         List actions = (List)map.get(name);
334 
335         if (actions == null) {
336             actions = new UniqueList();
337 
338             map.put(name, actions);
339         }
340 
341         return actions;
342     }
343 
344     private List _getModelPortletResources(String name) {
345         Set resources = (Set)_modelPortletResources.get(name);
346 
347         if (resources == null) {
348             return new UniqueList();
349         }
350         else {
351             return Collections.list(Collections.enumeration(resources));
352         }
353     }
354 
355     private List _getModelResourceActions(String name) {
356         return _getActions(_modelResourceActions, name);
357     }
358 
359     private List _getModelResourceCommunityDefaultActions(String name) {
360         return _getActions(_modelResourceCommunityDefaultActions, name);
361     }
362 
363     private List _getModelResourceGuestDefaultActions(String name) {
364         return _getActions(_modelResourceGuestDefaultActions, name);
365     }
366 
367     private List _getModelResourceGuestUnsupportedActions(String name) {
368         return _getActions(_modelResourceGuestUnsupportedActions, name);
369     }
370 
371     private List _getPortletModelResources(String portletName) {
372         portletName = PortletImpl.getRootPortletId(portletName);
373 
374         Set resources = (Set)_portletModelResources.get(portletName);
375 
376         if (resources == null) {
377             return new UniqueList();
378         }
379         else {
380             return Collections.list(Collections.enumeration(resources));
381         }
382     }
383 
384     private List _getPortletResourceActions(long companyId, String name)
385         throws SystemException {
386 
387         name = PortletImpl.getRootPortletId(name);
388 
389         List actions = _getActions(_portletResourceActions, name);
390 
391         if (actions.size() == 0) {
392             synchronized (this) {
393                 Portlet portlet = PortletLocalServiceUtil.getPortletById(
394                     companyId, name);
395 
396                 Map portletModes = portlet.getPortletModes();
397 
398                 Set mimeTypeModes = (Set)portletModes.get("text/html");
399 
400                 if (mimeTypeModes != null) {
401                     Iterator itr = mimeTypeModes.iterator();
402 
403                     while (itr.hasNext()) {
404                         String actionId = (String)itr.next();
405 
406                         if (actionId.equalsIgnoreCase("edit")) {
407                             actions.add(ActionKeys.PREFERENCES);
408                         }
409                         else if (actionId.equalsIgnoreCase("edit_guest")) {
410                             actions.add(ActionKeys.GUEST_PREFERENCES);
411                         }
412                         else {
413                             actions.add(actionId.toUpperCase());
414                         }
415                     }
416                 }
417 
418                 _checkPortletActions(actions);
419 
420                 List communityDefaultActions =
421                     (List)_portletResourceCommunityDefaultActions.get(name);
422 
423                 if (communityDefaultActions == null) {
424                     communityDefaultActions = new UniqueList();
425 
426                     _portletResourceCommunityDefaultActions.put(
427                         name, communityDefaultActions);
428 
429                     _checkPortletCommunityDefaultActions(
430                         communityDefaultActions);
431                 }
432 
433                 List guestDefaultActions =
434                     (List)_portletResourceGuestDefaultActions.get(name);
435 
436                 if (guestDefaultActions == null) {
437                     guestDefaultActions = new UniqueList();
438 
439                     _portletResourceGuestDefaultActions.put(
440                         name, guestDefaultActions);
441 
442                     _checkPortletGuestDefaultActions(guestDefaultActions);
443                 }
444             }
445         }
446 
447         return actions;
448     }
449 
450     private List _getPortletResourceCommunityDefaultActions(String name)
451         throws SystemException {
452 
453         // This method should always be called only after
454         // _getPortletResourceActions has been called at least once to
455         // populate the default community actions. Check to make sure this is
456         // the case. However, if it is not, that means the methods
457         // _getPortletResourceGuestDefaultActions and
458         // _getPortletResourceGuestDefaultActions may not work either.
459 
460         name = PortletImpl.getRootPortletId(name);
461 
462         return _getActions(_portletResourceCommunityDefaultActions, name);
463     }
464 
465     private List _getPortletResourceGuestDefaultActions(String name)
466         throws SystemException {
467 
468         name = PortletImpl.getRootPortletId(name);
469 
470         return _getActions(_portletResourceGuestDefaultActions, name);
471     }
472 
473     private List _getPortletResourceGuestUnsupportedActions(String name)
474         throws SystemException {
475 
476         name = PortletImpl.getRootPortletId(name);
477 
478         return _getActions(_portletResourceGuestUnsupportedActions, name);
479     }
480 
481     private void _read(
482             String servletContextName, ClassLoader classLoader, String source)
483         throws Exception {
484 
485         String xml = null;
486 
487         try {
488             xml = StringUtil.read(classLoader, source);
489         }
490         catch (Exception e) {
491             _log.warn("Cannot load " + source);
492         }
493 
494         if (xml == null) {
495             return;
496         }
497 
498         if (_log.isDebugEnabled()) {
499             _log.debug("Loading " + source);
500         }
501 
502         SAXReader reader = new SAXReader();
503 
504         Document doc = reader.read(new StringReader(xml));
505 
506         Element root = doc.getRootElement();
507 
508         Iterator itr1 = root.elements("resource").iterator();
509 
510         while (itr1.hasNext()) {
511             Element resource = (Element)itr1.next();
512 
513             String file = resource.attributeValue("file");
514 
515             _read(servletContextName, classLoader, file);
516         }
517 
518         itr1 = root.elements("portlet-resource").iterator();
519 
520         while (itr1.hasNext()) {
521             Element resource = (Element)itr1.next();
522 
523             String name = resource.elementText("portlet-name");
524 
525             if (servletContextName != null) {
526                 name = name + PortletImpl.WAR_SEPARATOR + servletContextName;
527             }
528 
529             name = PortalUtil.getJsSafePortletId(name);
530 
531             // Actions
532 
533             List actions = _getActions(_portletResourceActions, name);
534 
535             Element supports = resource.element("supports");
536 
537             Iterator itr2 = supports.elements("action-key").iterator();
538 
539             while (itr2.hasNext()) {
540                 Element actionKey = (Element)itr2.next();
541 
542                 String actionKeyText = actionKey.getText();
543 
544                 if (Validator.isNotNull(actionKeyText)) {
545                     actions.add(actionKeyText);
546                 }
547             }
548 
549             if (!name.equals(PortletKeys.PORTAL)) {
550                 _checkPortletActions(actions);
551             }
552 
553             // Community default actions
554 
555             List communityDefaultActions =
556                 _getActions(_portletResourceCommunityDefaultActions, name);
557 
558             Element communityDefaults = resource.element("community-defaults");
559 
560             itr2 = communityDefaults.elements("action-key").iterator();
561 
562             while (itr2.hasNext()) {
563                 Element actionKey = (Element)itr2.next();
564 
565                 String actionKeyText = actionKey.getText();
566 
567                 if (Validator.isNotNull(actionKeyText)) {
568                     communityDefaultActions.add(actionKeyText);
569                 }
570             }
571 
572             // Guest default actions
573 
574             List guestDefaultActions =
575                 _getActions(_portletResourceGuestDefaultActions, name);
576 
577             Element guestDefaults = resource.element("guest-defaults");
578 
579             itr2 = guestDefaults.elements("action-key").iterator();
580 
581             while (itr2.hasNext()) {
582                 Element actionKey = (Element)itr2.next();
583 
584                 String actionKeyText = actionKey.getText();
585 
586                 if (Validator.isNotNull(actionKeyText)) {
587                     guestDefaultActions.add(actionKeyText);
588                 }
589             }
590 
591             // Guest unsupported actions
592 
593             List guestUnsupportedActions =
594                 _getActions(_portletResourceGuestUnsupportedActions, name);
595 
596             Element guestUnsupported = resource.element("guest-unsupported");
597 
598             itr2 = guestUnsupported.elements("action-key").iterator();
599 
600             while (itr2.hasNext()) {
601                 Element actionKey = (Element)itr2.next();
602 
603                 String actionKeyText = actionKey.getText();
604 
605                 if (Validator.isNotNull(actionKeyText)) {
606                     guestUnsupportedActions.add(actionKeyText);
607                 }
608             }
609 
610             _checkGuestUnsupportedActions(
611                 guestUnsupportedActions, guestDefaultActions);
612         }
613 
614         itr1 = root.elements("model-resource").iterator();
615 
616         while (itr1.hasNext()) {
617             Element resource = (Element)itr1.next();
618 
619             String name = resource.elementText("model-name");
620 
621             Element portletRef = resource.element("portlet-ref");
622 
623             Iterator itr2 = portletRef.elements("portlet-name").iterator();
624 
625             while (itr2.hasNext()) {
626                 Element portletName = (Element)itr2.next();
627 
628                 String portletNameString = portletName.getText();
629 
630                 if (servletContextName != null) {
631                     portletNameString =
632                         portletNameString + PortletImpl.WAR_SEPARATOR +
633                             servletContextName;
634                 }
635 
636                 portletNameString = PortalUtil.getJsSafePortletId(
637                     portletNameString);
638 
639                 // Reference for a portlet to child models
640 
641                 Set modelResources = (Set)_portletModelResources.get(
642                     portletNameString);
643 
644                 if (modelResources == null) {
645                     modelResources = new HashSet();
646 
647                     _portletModelResources.put(
648                         portletNameString, modelResources);
649                 }
650 
651                 modelResources.add(name);
652 
653                 // Reference for a model to parent portlets
654 
655                 Set portletResources = (Set)_modelPortletResources.get(name);
656 
657                 if (portletResources == null) {
658                     portletResources = new HashSet();
659 
660                     _modelPortletResources.put(name, portletResources);
661                 }
662 
663                 portletResources.add(portletNameString);
664             }
665 
666             // Actions
667 
668             List actions = _getActions(_modelResourceActions, name);
669 
670             Element supports = resource.element("supports");
671 
672             itr2 = supports.elements("action-key").iterator();
673 
674             while (itr2.hasNext()) {
675                 Element actionKey = (Element)itr2.next();
676 
677                 String actionKeyText = actionKey.getText();
678 
679                 if (Validator.isNotNull(actionKeyText)) {
680                     actions.add(actionKeyText);
681                 }
682             }
683 
684             // Community default actions
685 
686             List communityDefaultActions =
687                 _getActions(_modelResourceCommunityDefaultActions, name);
688 
689             Element communityDefaults = resource.element("community-defaults");
690 
691             itr2 = communityDefaults.elements("action-key").iterator();
692 
693             while (itr2.hasNext()) {
694                 Element actionKey = (Element)itr2.next();
695 
696                 String actionKeyText = actionKey.getText();
697 
698                 if (Validator.isNotNull(actionKeyText)) {
699                     communityDefaultActions.add(actionKeyText);
700                 }
701             }
702 
703             // Guest default actions
704 
705             List guestDefaultActions =
706                 _getActions(_modelResourceGuestDefaultActions, name);
707 
708             Element guestDefaults = resource.element("guest-defaults");
709 
710             itr2 = guestDefaults.elements("action-key").iterator();
711 
712             while (itr2.hasNext()) {
713                 Element actionKey = (Element)itr2.next();
714 
715                 String actionKeyText = actionKey.getText();
716 
717                 if (Validator.isNotNull(actionKeyText)) {
718                     guestDefaultActions.add(actionKeyText);
719                 }
720             }
721 
722             // Guest unsupported actions
723 
724             List guestUnsupportedActions =
725                 _getActions(_modelResourceGuestUnsupportedActions, name);
726 
727             Element guestUnsupported = resource.element("guest-unsupported");
728 
729             itr2 = guestUnsupported.elements("action-key").iterator();
730 
731             while (itr2.hasNext()) {
732                 Element actionKey = (Element)itr2.next();
733 
734                 String actionKeyText = actionKey.getText();
735 
736                 if (Validator.isNotNull(actionKeyText)) {
737                     guestUnsupportedActions.add(actionKeyText);
738                 }
739             }
740 
741             _checkGuestUnsupportedActions(
742                 guestUnsupportedActions, guestDefaultActions);
743         }
744     }
745 
746     private static Log _log = LogFactory.getLog(ResourceActionsUtil.class);
747 
748     private static ResourceActionsUtil _instance = new ResourceActionsUtil();
749 
750     private Map _portletModelResources;
751     private Map _portletResourceActions;
752     private Map _portletResourceCommunityDefaultActions;
753     private Map _portletResourceGuestDefaultActions;
754     private Map _portletResourceGuestUnsupportedActions;
755     private Map _modelPortletResources;
756     private Map _modelResourceActions;
757     private Map _modelResourceCommunityDefaultActions;
758     private Map _modelResourceGuestDefaultActions;
759     private Map _modelResourceGuestUnsupportedActions;
760 
761 }