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