001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cluster;
016    
017    import com.liferay.portal.bean.IdentifiableBeanInvokerUtil;
018    import com.liferay.portal.kernel.cluster.ClusterInvokeAcceptor;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.GroupThreadLocal;
021    import com.liferay.portal.kernel.util.LocaleThreadLocal;
022    import com.liferay.portal.kernel.util.MethodHandler;
023    import com.liferay.portal.kernel.util.MethodKey;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.model.User;
026    import com.liferay.portal.security.auth.CompanyThreadLocal;
027    import com.liferay.portal.security.auth.PrincipalThreadLocal;
028    import com.liferay.portal.security.permission.PermissionChecker;
029    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
030    import com.liferay.portal.security.permission.PermissionThreadLocal;
031    import com.liferay.portal.service.UserLocalServiceUtil;
032    
033    import java.io.Serializable;
034    
035    import java.lang.reflect.Constructor;
036    
037    import java.util.Locale;
038    import java.util.Map;
039    
040    import org.aopalliance.intercept.MethodInvocation;
041    
042    /**
043     * @author Shuyang Zhou
044     */
045    public class ClusterableInvokerUtil {
046    
047            public static MethodHandler createMethodHandler(
048                    Class<? extends ClusterInvokeAcceptor> clusterInvokeAcceptorClass,
049                    MethodInvocation methodInvocation) {
050    
051                    MethodHandler methodHandler =
052                            IdentifiableBeanInvokerUtil.createMethodHandler(methodInvocation);
053    
054                    Map<String, Serializable> context =
055                            ClusterableContextThreadLocal.collectThreadLocalContext();
056    
057                    _populateContextFromThreadLocals(context);
058    
059                    if (clusterInvokeAcceptorClass == ClusterInvokeAcceptor.class) {
060                            clusterInvokeAcceptorClass = null;
061                    }
062    
063                    return new MethodHandler(
064                            _invokeMethodKey, methodHandler, clusterInvokeAcceptorClass,
065                            context);
066            }
067    
068            @SuppressWarnings("unused")
069            private static Object _invoke(
070                            MethodHandler methodHandler,
071                            Class<? extends ClusterInvokeAcceptor> clusterInvokeAcceptorClass,
072                            Map<String, Serializable> context)
073                    throws Exception {
074    
075                    if (clusterInvokeAcceptorClass != null) {
076                            Constructor<? extends ClusterInvokeAcceptor> constructor =
077                                    clusterInvokeAcceptorClass.getDeclaredConstructor();
078    
079                            if (!constructor.isAccessible()) {
080                                    constructor.setAccessible(true);
081                            }
082    
083                            ClusterInvokeAcceptor clusterInvokeAcceptor =
084                                    constructor.newInstance();
085    
086                            if (!clusterInvokeAcceptor.accept(context)) {
087                                    return null;
088                            }
089                    }
090    
091                    _populateThreadLocalsFromContext(context);
092    
093                    return methodHandler.invoke(false);
094            }
095    
096            private static void _populateContextFromThreadLocals(
097                    Map<String, Serializable> context) {
098    
099                    if (!context.containsKey("companyId")) {
100                            context.put("companyId", CompanyThreadLocal.getCompanyId());
101                    }
102    
103                    if (!context.containsKey("defaultLocale")) {
104                            context.put("defaultLocale", LocaleThreadLocal.getDefaultLocale());
105                    }
106    
107                    if (!context.containsKey("groupId")) {
108                            context.put("groupId", GroupThreadLocal.getGroupId());
109                    }
110    
111                    if (!context.containsKey("principalName")) {
112                            context.put("principalName", PrincipalThreadLocal.getName());
113                    }
114    
115                    if (!context.containsKey("principalPassword")) {
116                            context.put(
117                                    "principalPassword", PrincipalThreadLocal.getPassword());
118                    }
119    
120                    if (!context.containsKey("siteDefaultLocale")) {
121                            context.put(
122                                    "siteDefaultLocale", LocaleThreadLocal.getSiteDefaultLocale());
123                    }
124    
125                    if (!context.containsKey("themeDisplayLocale")) {
126                            context.put(
127                                    "themeDisplayLocale",
128                                    LocaleThreadLocal.getThemeDisplayLocale());
129                    }
130            }
131    
132            private static void _populateThreadLocalsFromContext(
133                    Map<String, Serializable> context) {
134    
135                    long companyId = GetterUtil.getLong(context.get("companyId"));
136    
137                    if (companyId > 0) {
138                            CompanyThreadLocal.setCompanyId(companyId);
139                    }
140    
141                    Locale defaultLocale = (Locale)context.get("defaultLocale");
142    
143                    if (defaultLocale != null) {
144                            LocaleThreadLocal.setDefaultLocale(defaultLocale);
145                    }
146    
147                    long groupId = GetterUtil.getLong(context.get("groupId"));
148    
149                    if (groupId > 0) {
150                            GroupThreadLocal.setGroupId(groupId);
151                    }
152    
153                    String principalName = GetterUtil.getString(
154                            context.get("principalName"));
155    
156                    if (Validator.isNotNull(principalName)) {
157                            PrincipalThreadLocal.setName(principalName);
158                    }
159    
160                    PermissionChecker permissionChecker = null;
161    
162                    if (Validator.isNotNull(principalName)) {
163                            try {
164                                    User user = UserLocalServiceUtil.fetchUser(
165                                            PrincipalThreadLocal.getUserId());
166    
167                                    permissionChecker = PermissionCheckerFactoryUtil.create(user);
168                            }
169                            catch (Exception e) {
170                                    throw new RuntimeException(e);
171                            }
172                    }
173    
174                    if (permissionChecker != null) {
175                            PermissionThreadLocal.setPermissionChecker(permissionChecker);
176                    }
177    
178                    String principalPassword = GetterUtil.getString(
179                            context.get("principalPassword"));
180    
181                    if (Validator.isNotNull(principalPassword)) {
182                            PrincipalThreadLocal.setPassword(principalPassword);
183                    }
184    
185                    Locale siteDefaultLocale = (Locale)context.get("siteDefaultLocale");
186    
187                    if (siteDefaultLocale != null) {
188                            LocaleThreadLocal.setSiteDefaultLocale(siteDefaultLocale);
189                    }
190    
191                    Locale themeDisplayLocale = (Locale)context.get("themeDisplayLocale");
192    
193                    if (themeDisplayLocale != null) {
194                            LocaleThreadLocal.setThemeDisplayLocale(themeDisplayLocale);
195                    }
196            }
197    
198            private static MethodKey _invokeMethodKey = new MethodKey(
199                    ClusterableInvokerUtil.class, "_invoke", MethodHandler.class,
200                    Class.class, Map.class);
201    
202    }