001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.util.bridges.alloy;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
020    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
021    import com.liferay.portal.kernel.servlet.SessionMessages;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.JavaConstants;
024    import com.liferay.portal.kernel.util.ParamUtil;
025    import com.liferay.portal.kernel.util.StringBundler;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.model.Portlet;
029    import com.liferay.portal.util.PortalUtil;
030    
031    import java.lang.reflect.Method;
032    
033    import java.util.HashMap;
034    import java.util.Map;
035    
036    import javax.portlet.ActionRequest;
037    import javax.portlet.ActionResponse;
038    import javax.portlet.EventRequest;
039    import javax.portlet.EventResponse;
040    import javax.portlet.PortletContext;
041    import javax.portlet.PortletRequest;
042    import javax.portlet.PortletRequestDispatcher;
043    import javax.portlet.PortletResponse;
044    import javax.portlet.PortletURL;
045    import javax.portlet.RenderRequest;
046    import javax.portlet.RenderResponse;
047    import javax.portlet.ResourceRequest;
048    import javax.portlet.ResourceResponse;
049    
050    import javax.servlet.ServletConfig;
051    import javax.servlet.ServletContext;
052    import javax.servlet.http.HttpServletRequest;
053    import javax.servlet.http.HttpServletResponse;
054    import javax.servlet.jsp.PageContext;
055    
056    /**
057     * @author Brian Wing Shun Chan
058     */
059    public abstract class BaseAlloyControllerImpl implements AlloyController {
060    
061            public void afterPropertiesSet() {
062                    initClass();
063                    initServletVariables();
064                    initPortletVariables();
065                    initMethods();
066                    initPaths();
067            }
068    
069            public void execute() throws Exception {
070                    Method method = getMethod(actionPath);
071    
072                    if (method == null) {
073                            if (log.isDebugEnabled()) {
074                                    log.debug("No method found for action " + actionPath);
075                            }
076                    }
077    
078                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
079                            executeAction(method);
080                    }
081                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
082                            executeRender(method);
083                    }
084            }
085    
086            public void setPageContext(PageContext pageContext) {
087                    this.pageContext = pageContext;
088            }
089    
090            protected void addSuccessMessage() {
091                    String successMessage = ParamUtil.getString(
092                            portletRequest, "successMessage");
093    
094                    SessionMessages.add(
095                            portletRequest, "request_processed", successMessage);
096            }
097    
098            protected String buildIncludePath(String viewPath) {
099                    StringBundler sb = new StringBundler(7);
100    
101                    sb.append("/WEB-INF/jsp/");
102                    sb.append(portlet.getFriendlyURLMapping());
103                    sb.append("/views/");
104                    sb.append(controllerPath);
105                    sb.append(StringPool.SLASH);
106                    sb.append(viewPath);
107                    sb.append(".jsp");
108    
109                    return sb.toString();
110            }
111    
112            protected void executeAction(Method method) throws Exception {
113                    if (method != null) {
114                            method.invoke(this);
115                    }
116    
117                    actionRequest.setAttribute(
118                            CALLED_PROCESS_ACTION, Boolean.TRUE.toString());
119    
120                    if (Validator.isNotNull(viewPath)) {
121                            actionRequest.setAttribute(VIEW_PATH, viewPath);
122    
123                            PortalUtil.copyRequestParameters(actionRequest, actionResponse);
124                    }
125                    else if (Validator.isNotNull(redirect)) {
126                            actionResponse.sendRedirect(redirect);
127                    }
128            }
129    
130            protected void executeRender(Method method) throws Exception {
131                    boolean calledProcessAction = GetterUtil.getBoolean(
132                            (String)request.getAttribute(CALLED_PROCESS_ACTION));
133    
134                    if (!calledProcessAction) {
135                            if (method != null) {
136                                    method.invoke(this);
137                            }
138                    }
139    
140                    if (Validator.isNull(viewPath)) {
141                            viewPath = actionPath;
142                    }
143    
144                    String includePath = buildIncludePath(viewPath);
145    
146                    PortletRequestDispatcher portletRequestDispatcher =
147                            portletContext.getRequestDispatcher(includePath);
148    
149                    if (portletRequestDispatcher == null) {
150                            log.error(includePath + " is not a valid include");
151                    }
152                    else {
153                            portletRequestDispatcher.include(
154                                    portletRequest, portletResponse);
155                    }
156            }
157    
158            protected Method getMethod(String methodName, Class<?>... parameterTypes) {
159                    String methodKey = getMethodKey(methodName, parameterTypes);
160    
161                    return methodsMap.get(methodKey);
162            }
163    
164            protected String getMethodKey(
165                    String methodName, Class<?>... parameterTypes) {
166    
167                    StringBundler sb = new StringBundler(parameterTypes.length * 2 + 2);
168    
169                    sb.append(methodName);
170                    sb.append(StringPool.POUND);
171    
172                    for (Class<?> parameterType : parameterTypes) {
173                            sb.append(parameterType.getName());
174                            sb.append(StringPool.POUND);
175                    }
176    
177                    return sb.toString();
178            }
179    
180            protected void initClass() {
181                    clazz = getClass();
182                    classLoader = clazz.getClassLoader();
183            }
184    
185            protected void initMethods() {
186                    methodsMap = new HashMap<String, Method>();
187    
188                    Method[] methods = clazz.getMethods();
189    
190                    for (Method method : methods) {
191                            String methodKey = getMethodKey(
192                                    method.getName(), method.getParameterTypes());
193    
194                            methodsMap.put(methodKey, method);
195                    }
196            }
197    
198            protected void initPaths() {
199                    controllerPath = ParamUtil.getString(request, "controller");
200    
201                    if (Validator.isNull(controllerPath)) {
202                            Map<String, String> defaultRouteParameters =
203                                    alloyPortlet.getDefaultRouteParameters();
204    
205                            controllerPath = defaultRouteParameters.get("controller");
206                    }
207    
208                    if (log.isDebugEnabled()) {
209                            log.debug("Controller path " + controllerPath);
210                    }
211    
212                    actionPath = ParamUtil.getString(request, "action");
213    
214                    if (Validator.isNull(actionPath)) {
215                            Map<String, String> defaultRouteParameters =
216                                    alloyPortlet.getDefaultRouteParameters();
217    
218                            actionPath = defaultRouteParameters.get("action");
219                    }
220    
221                    if (log.isDebugEnabled()) {
222                            log.debug("Action path " + actionPath);
223                    }
224    
225                    viewPath = GetterUtil.getString(
226                            (String)request.getAttribute(VIEW_PATH));
227    
228                    request.removeAttribute(VIEW_PATH);
229    
230                    if (log.isDebugEnabled()) {
231                            log.debug("View path " + viewPath);
232                    }
233            }
234    
235            protected void initPortletVariables() {
236                    liferayPortletConfig = (LiferayPortletConfig)request.getAttribute(
237                            JavaConstants.JAVAX_PORTLET_CONFIG);
238    
239                    portletContext = liferayPortletConfig.getPortletContext();
240    
241                    portlet = liferayPortletConfig.getPortlet();
242    
243                    alloyPortlet = (AlloyPortlet)request.getAttribute(
244                            JavaConstants.JAVAX_PORTLET_PORTLET);
245    
246                    portletRequest = (PortletRequest)request.getAttribute(
247                            JavaConstants.JAVAX_PORTLET_REQUEST);
248                    portletResponse = (PortletResponse)request.getAttribute(
249                            JavaConstants.JAVAX_PORTLET_RESPONSE);
250    
251                    liferayPortletResponse = (LiferayPortletResponse)portletResponse;
252    
253                    lifecycle = GetterUtil.getString(
254                            (String)request.getAttribute(PortletRequest.LIFECYCLE_PHASE));
255    
256                    if (log.isDebugEnabled()) {
257                            log.debug("Lifecycle " + lifecycle);
258                    }
259    
260                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
261                            actionRequest = (ActionRequest)portletRequest;
262                            actionResponse = (ActionResponse)portletResponse;
263                    }
264                    else if (lifecycle.equals(PortletRequest.EVENT_PHASE)) {
265                            eventRequest = (EventRequest)portletRequest;
266                            eventResponse = (EventResponse)portletResponse;
267                    }
268                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
269                            renderRequest = (RenderRequest)portletRequest;
270                            renderResponse = (RenderResponse)portletResponse;
271                    }
272                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
273                            resourceRequest = (ResourceRequest)portletRequest;
274                            resourceResponse = (ResourceResponse)portletResponse;
275                    }
276            }
277    
278            protected void initServletVariables() {
279                    servletConfig = pageContext.getServletConfig();
280                    servletContext = pageContext.getServletContext();
281                    request = (HttpServletRequest)pageContext.getRequest();
282                    response = (HttpServletResponse)pageContext.getResponse();
283            }
284    
285            protected void redirectTo(PortletURL portletURL) {
286                    redirectTo(portletURL.toString());
287            }
288    
289            protected void redirectTo(String redirect) {
290                    if (!lifecycle.equals(PortletRequest.ACTION_PHASE)) {
291                            throw new IllegalArgumentException(
292                                    "redirectTo can only be called during the action phase");
293                    }
294    
295                    if (Validator.isNotNull(viewPath)) {
296                            throw new IllegalArgumentException(
297                                    "redirectTo cannot be called if render has been called");
298                    }
299    
300                    this.redirect = redirect;
301            }
302    
303            protected void render(String actionPath) {
304                    if (Validator.isNotNull(redirect)) {
305                            throw new IllegalArgumentException(
306                                    "render cannot be called if redirectTo has been called");
307                    }
308    
309                    viewPath = actionPath;
310            }
311    
312            protected static final String CALLED_PROCESS_ACTION =
313                    "CALLED_PROCESS_ACTION";
314    
315            protected static final String VIEW_PATH = "VIEW_PATH";
316    
317            protected static Log log = LogFactoryUtil.getLog(
318                    BaseAlloyControllerImpl.class);
319    
320            protected String actionPath;
321            protected ActionRequest actionRequest;
322            protected ActionResponse actionResponse;
323            protected AlloyPortlet alloyPortlet;
324            protected ClassLoader classLoader;
325            protected Class<?> clazz;
326            protected String controllerPath;
327            protected EventRequest eventRequest;
328            protected EventResponse eventResponse;
329            protected String lifecycle;
330            protected LiferayPortletConfig liferayPortletConfig;
331            protected LiferayPortletResponse liferayPortletResponse;
332            protected Map<String, Method> methodsMap;
333            protected PageContext pageContext;
334            protected Portlet portlet;
335            protected PortletContext portletContext;
336            protected PortletRequest portletRequest;
337            protected PortletResponse portletResponse;
338            protected String redirect;
339            protected RenderRequest renderRequest;
340            protected RenderResponse renderResponse;
341            protected HttpServletRequest request;
342            protected ResourceRequest resourceRequest;
343            protected ResourceResponse resourceResponse;
344            protected HttpServletResponse response;
345            protected ServletConfig servletConfig;
346            protected ServletContext servletContext;
347            protected String viewPath;
348    
349    }