MainServlet中,当处理完全局启动事件,比如插件自动部署目录的设定之后,就开始初始化Resource Action,其代码如下:

   
   
   
   
  1.     if (_log.isDebugEnabled()) { 
  2.             _log.debug("Initialize resource actions"); 
  3.         } 
  4.  
  5.         try { 
  6.             initResourceActions(portlets); 
  7.         } 
  8. .. 

 

它调用了initResourceActions方法,我们看它做了什么事情:

首先,它对PERMISSIONS_USER_CHECK_ALGORITHM的设定必须是6以上,否则就返回:

   
   
   
   
  1. if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 6) { 
  2.             if (_log.isWarnEnabled()) { 
  3.                 StringBundler sb = new StringBundler(8); 
  4.  
  5.                 sb.append("Liferay is configured to use permission algorithm "); 
  6.                 sb.append(PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM); 
  7.                 sb.append(". Versions after 6.1 will only support algorithm "); 
  8.                 sb.append("6 and above. Please sign in as an administrator, "); 
  9. ... 
  10.  
  11.                 _log.warn(sb.toString()); 
  12.             } 
  13.  
  14.             return
  15.         } 

这个设定在portal.properties文件中,Liferay 6 默认的设置为6:

   
   
   
   
  1.   # Set the algorithm used to check permissions for a user. This is useful so 
  2.   # that you can optimize the search for different databases. See 
  3.   # com.liferay.portal.service.impl.PermissionLocalServiceImpl. 
  4.   # 
  5.   # Algorithms 1 through 4 are essentially the same but make calls in different 
  6.   # orders depending on how the database is optimized and how the portal 
  7.   # permissions are used. Algorithm 5 moves to a completely role based 
  8.   # permissions check for better performance. Permissions by users are no 
  9.   # longer supported, yet it uses the same table structure as algorithms 1-4. 
  10.   # 
  11.   # Algorithm 6 is the current algorithm for Liferay 6 and above. It supports 
  12.   # role based permissions like algorithm 5, but does so by using only one 
  13.   # table and bitwise operations. This makes it perform far better than the 
  14.   # other algorithms. 
  15.   # 
  16.   #permissions.user.check.algorithm=1 
  17.   #permissions.user.check.algorithm=2 
  18.   #permissions.user.check.algorithm=3 
  19.   #permissions.user.check.algorithm=4 
  20.   #permissions.user.check.algorithm=5 
  21.   permissions.user.check.algorithm=6 

 

然后,它对参数中的每个portlet进行迭代,找出ResourceActions进行处理:

   
   
   
   
  1. while (itr.hasNext()) { 
  2.             Portlet portlet = itr.next(); 
  3.  
  4.             List portletActions = 
  5.                 ResourceActionsUtil.getPortletResourceActions(portlet); 
  6.  
  7.             ResourceActionLocalServiceUtil.checkResourceActions( 
  8.                 portlet.getPortletId(), portletActions); 
  9.  
  10.             List modelNames = 
  11.                 ResourceActionsUtil.getPortletModelResources( 
  12.                     portlet.getPortletId()); 
  13.  
  14.             for (String modelName : modelNames) { 
  15.                 List modelActions = 
  16.                     ResourceActionsUtil.getModelResourceActions(modelName); 
  17.  
  18.                 ResourceActionLocalServiceUtil.checkResourceActions( 
  19.                     modelName, modelActions); 
  20.             } 
  21.         } 

 

我们逐行分析。

分析04-05行:

在第04行,它调用ResourceActionsUtil的getPortletResourceActions方法来获取和某个portlet相关联的portletActions列表:

   
   
   
   
  1. public static List getPortletResourceActions(Portlet portlet) { 
  2.         return getResourceActions().getPortletResourceActions(portlet); 
  3.     } 

它会去委托ResourceActionImpl的getPortletResourceActions方法:

   
   
   
   
  1. public List getPortletResourceActions(Portlet portlet) { 
  2.         List actions = ListUtil.copy( 
  3.             getPortletResourceActions(portlet.getPortletId())); 
  4.  
  5.         synchronized (this) { 
  6.             checkPortletActions(portlet, actions); 
  7.  
  8.             setActions( 
  9.                 _portletResourceActions, portlet.getPortletId(), actions); 
  10.         } 
  11.  
  12.         return actions; 
  13.     } 

从第3行又可以看出,它是从portlet得到其id然后传递给重载的另一个方法:

   
   
   
   
  1. public List getPortletResourceActions(String name) { 
  2.         name = PortletConstants.getRootPortletId(name); 
  3.  
  4.         List actions = getActions(_portletResourceActions, name); 
  5.  
  6.         if (!actions.isEmpty()) { 
  7.             return actions; 
  8.         } 
  9.  
  10.         synchronized (this) { 
  11.             actions = getPortletMimeTypeActions(name); 
  12.  
  13.             if (!name.equals(PortletKeys.PORTAL)) { 
  14.                 checkPortletActions(name, actions); 
  15.             } 
  16.  
  17.             List groupDefaultActions = 
  18.                 _portletResourceGroupDefaultActions.get(name); 
  19.  
  20.             if (groupDefaultActions == null) { 
  21.                 groupDefaultActions = new UniqueList(); 
  22.  
  23.                 checkPortletGroupDefaultActions(groupDefaultActions); 
  24.  
  25.                 _portletResourceGroupDefaultActions.put( 
  26.                     name, new UnmodifiableList(groupDefaultActions)); 
  27.             } 
  28.  
  29.             List guestDefaultActions = 
  30.                 _portletResourceGuestDefaultActions.get(name); 
  31.  
  32.             if (guestDefaultActions == null) { 
  33.                 guestDefaultActions = new UniqueList(); 
  34.  
  35.                 checkPortletGuestDefaultActions(guestDefaultActions); 
  36.  
  37.                 _portletResourceGuestDefaultActions.put( 
  38.                     name, new UnmodifiableList(guestDefaultActions)); 
  39.             } 
  40.  
  41.             List layoutManagerActions = 
  42.                 _portletResourceLayoutManagerActions.get(name); 
  43.  
  44.             if (layoutManagerActions == null) { 
  45.                 layoutManagerActions = new UniqueList(); 
  46.  
  47.                 checkPortletLayoutManagerActions(layoutManagerActions); 
  48.  
  49.                 _portletResourceLayoutManagerActions.put( 
  50.                     name, new UnmodifiableList(layoutManagerActions)); 
  51.             } 
  52.  
  53.             actions = setActions(_portletResourceActions, name, actions); 
  54.         } 
  55.  
  56.         return actions; 
  57.     } 

这里跟进每一步都会很复杂,我们一步一步来,第11行可以根据portlet的name来获得portlet的mode ,并且根据mode的设定来得到它的action,是edit还是edit_guest.第17-27行去检查group的默认action,吧group的默认action设置为view.29-39行去检查guest的默认action,把guest的默认action设置为view.第41-51行去检查layoutManager的action,它会为每个layoutManager都添加4种action(CONFIGURATION,PERMISSIONS,PERFERENCES和VIEW)

 

所以概括来说,04行就是检查并且获取每个portlet的action设置,包括自身action,group action,guest action,layout manager action.

 

分析07-08行:

07行中,它会调用ResourceActionLocalServiceUtil的checkResourceActions方法:

   
   
   
   
  1. public static void checkResourceActions(java.lang.String name, 
  2.         java.util.List actionIds) 
  3.         throws com.liferay.portal.kernel.exception.SystemException { 
  4.         getService().checkResourceActions(name, actionIds); 
  5.     } 

它最终实际会委托ResourceActionLocalServiceImpl的checkResourceActions方法:

   
   
   
   
  1. public void checkResourceActions( 
  2.             String name, List actionIds, boolean addDefaultActions) 
  3.         throws SystemException { 
  4.  
  5.         if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) { 
  6.             return
  7.         } 
  8.  
  9.         List resourceActions = 
  10.             resourceActionPersistence.findByName(name); 
  11.  
  12.         resourceActions = ListUtil.copy(resourceActions); 
  13.  
  14.         checkResourceActions( 
  15.             name, actionIds, resourceActions, addDefaultActions); 
  16.     } 

从这里可以看出,它第05-06行先确保user permission check被设置为6,然后它在09-10行中从数据库中取得与portlet名字对应的resource actions列表,最后来检查数据库中的resource actions是否和先前从04-05步的相一致。

 

分析第10-20行:

它从portlet分离出对应的portlet mode的所有action,然后在继续刚才的分析,这里就不一一详细分析了。

 

所以,初始化resource action之后,系统就对每个portle有哪些action十分清楚了。