001    /**
002     * Copyright (c) 2000-2011 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.util.bridges.alloy;
016    
017    import com.liferay.counter.service.CounterLocalServiceUtil;
018    import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
022    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
023    import com.liferay.portal.kernel.portlet.PortletResponseUtil;
024    import com.liferay.portal.kernel.search.Indexer;
025    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
026    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
027    import com.liferay.portal.kernel.servlet.SessionMessages;
028    import com.liferay.portal.kernel.util.ContentTypes;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.JavaConstants;
031    import com.liferay.portal.kernel.util.ParamUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.util.WebKeys;
036    import com.liferay.portal.model.AttachedModel;
037    import com.liferay.portal.model.AuditedModel;
038    import com.liferay.portal.model.BaseModel;
039    import com.liferay.portal.model.Company;
040    import com.liferay.portal.model.GroupedModel;
041    import com.liferay.portal.model.PersistedModel;
042    import com.liferay.portal.model.Portlet;
043    import com.liferay.portal.model.User;
044    import com.liferay.portal.theme.ThemeDisplay;
045    import com.liferay.portal.util.PortalUtil;
046    
047    import java.lang.reflect.Method;
048    
049    import java.util.Date;
050    import java.util.HashMap;
051    import java.util.Map;
052    
053    import javax.portlet.ActionRequest;
054    import javax.portlet.ActionResponse;
055    import javax.portlet.EventRequest;
056    import javax.portlet.EventResponse;
057    import javax.portlet.MimeResponse;
058    import javax.portlet.PortletContext;
059    import javax.portlet.PortletRequest;
060    import javax.portlet.PortletRequestDispatcher;
061    import javax.portlet.PortletResponse;
062    import javax.portlet.PortletURL;
063    import javax.portlet.RenderRequest;
064    import javax.portlet.RenderResponse;
065    import javax.portlet.ResourceRequest;
066    import javax.portlet.ResourceResponse;
067    
068    import javax.servlet.ServletConfig;
069    import javax.servlet.ServletContext;
070    import javax.servlet.http.HttpServletRequest;
071    import javax.servlet.http.HttpServletResponse;
072    import javax.servlet.jsp.PageContext;
073    
074    /**
075     * @author Brian Wing Shun Chan
076     */
077    public abstract class BaseAlloyControllerImpl implements AlloyController {
078    
079            public void afterPropertiesSet() {
080                    initClass();
081                    initServletVariables();
082                    initPortletVariables();
083                    initThemeDisplayVariables();
084                    initMethods();
085                    initPaths();
086                    initIndexer();
087            }
088    
089            public void execute() throws Exception {
090                    Method method = getMethod(actionPath);
091    
092                    if (method == null) {
093                            if (log.isDebugEnabled()) {
094                                    log.debug("No method found for action " + actionPath);
095                            }
096                    }
097    
098                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
099                            executeAction(method);
100                    }
101                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
102                            executeRender(method);
103                    }
104                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
105                            executeResource(method);
106                    }
107            }
108    
109            public void setPageContext(PageContext pageContext) {
110                    this.pageContext = pageContext;
111            }
112    
113            protected void addSuccessMessage() {
114                    String successMessage = ParamUtil.getString(
115                            portletRequest, "successMessage");
116    
117                    SessionMessages.add(
118                            portletRequest, "request_processed", successMessage);
119            }
120    
121            protected String buildIncludePath(String viewPath) {
122                    StringBundler sb = new StringBundler(7);
123    
124                    sb.append("/WEB-INF/jsp/");
125                    sb.append(portlet.getFriendlyURLMapping());
126                    sb.append("/views/");
127                    sb.append(controllerPath);
128                    sb.append(StringPool.SLASH);
129                    sb.append(viewPath);
130                    sb.append(".jsp");
131    
132                    return sb.toString();
133            }
134    
135            protected Indexer buildIndexer() {
136                    return null;
137            }
138    
139            protected void executeAction(Method method) throws Exception {
140                    if (method != null) {
141                            method.invoke(this);
142                    }
143    
144                    actionRequest.setAttribute(
145                            CALLED_PROCESS_ACTION, Boolean.TRUE.toString());
146    
147                    if (Validator.isNotNull(viewPath)) {
148                            actionRequest.setAttribute(VIEW_PATH, viewPath);
149    
150                            PortalUtil.copyRequestParameters(actionRequest, actionResponse);
151                    }
152                    else if (Validator.isNotNull(redirect)) {
153                            actionResponse.sendRedirect(redirect);
154                    }
155            }
156    
157            protected void executeRender(Method method) throws Exception {
158                    boolean calledProcessAction = GetterUtil.getBoolean(
159                            (String)request.getAttribute(CALLED_PROCESS_ACTION));
160    
161                    if (!calledProcessAction) {
162                            if (method != null) {
163                                    method.invoke(this);
164                            }
165                    }
166    
167                    if (Validator.isNull(viewPath)) {
168                            viewPath = actionPath;
169                    }
170    
171                    String includePath = buildIncludePath(viewPath);
172    
173                    PortletRequestDispatcher portletRequestDispatcher =
174                            portletContext.getRequestDispatcher(includePath);
175    
176                    if (portletRequestDispatcher == null) {
177                            log.error(includePath + " is not a valid include");
178                    }
179                    else {
180                            portletRequestDispatcher.include(
181                                    portletRequest, portletResponse);
182                    }
183            }
184    
185            protected void executeResource(Method method) throws Exception {
186                    if (method != null) {
187                            method.invoke(this);
188                    }
189            }
190    
191            protected Method getMethod(String methodName, Class<?>... parameterTypes) {
192                    String methodKey = getMethodKey(methodName, parameterTypes);
193    
194                    return methodsMap.get(methodKey);
195            }
196    
197            protected String getMethodKey(
198                    String methodName, Class<?>... parameterTypes) {
199    
200                    StringBundler sb = new StringBundler(parameterTypes.length * 2 + 2);
201    
202                    sb.append(methodName);
203                    sb.append(StringPool.POUND);
204    
205                    for (Class<?> parameterType : parameterTypes) {
206                            sb.append(parameterType.getName());
207                            sb.append(StringPool.POUND);
208                    }
209    
210                    return sb.toString();
211            }
212    
213            protected void initClass() {
214                    clazz = getClass();
215                    classLoader = clazz.getClassLoader();
216            }
217    
218            protected void initIndexer() {
219                    indexer = buildIndexer();
220    
221                    if (indexer != null) {
222                            IndexerRegistryUtil.register(indexer);
223                    }
224            }
225    
226            protected void initMethods() {
227                    methodsMap = new HashMap<String, Method>();
228    
229                    Method[] methods = clazz.getMethods();
230    
231                    for (Method method : methods) {
232                            String methodKey = getMethodKey(
233                                    method.getName(), method.getParameterTypes());
234    
235                            methodsMap.put(methodKey, method);
236                    }
237            }
238    
239            protected void initPaths() {
240                    controllerPath = ParamUtil.getString(request, "controller");
241    
242                    if (Validator.isNull(controllerPath)) {
243                            Map<String, String> defaultRouteParameters =
244                                    alloyPortlet.getDefaultRouteParameters();
245    
246                            controllerPath = defaultRouteParameters.get("controller");
247                    }
248    
249                    if (log.isDebugEnabled()) {
250                            log.debug("Controller path " + controllerPath);
251                    }
252    
253                    actionPath = ParamUtil.getString(request, "action");
254    
255                    if (Validator.isNull(actionPath)) {
256                            Map<String, String> defaultRouteParameters =
257                                    alloyPortlet.getDefaultRouteParameters();
258    
259                            actionPath = defaultRouteParameters.get("action");
260                    }
261    
262                    if (log.isDebugEnabled()) {
263                            log.debug("Action path " + actionPath);
264                    }
265    
266                    viewPath = GetterUtil.getString(
267                            (String)request.getAttribute(VIEW_PATH));
268    
269                    request.removeAttribute(VIEW_PATH);
270    
271                    if (log.isDebugEnabled()) {
272                            log.debug("View path " + viewPath);
273                    }
274            }
275    
276            protected void initPortletVariables() {
277                    liferayPortletConfig = (LiferayPortletConfig)request.getAttribute(
278                            JavaConstants.JAVAX_PORTLET_CONFIG);
279    
280                    portletContext = liferayPortletConfig.getPortletContext();
281    
282                    portlet = liferayPortletConfig.getPortlet();
283    
284                    alloyPortlet = (AlloyPortlet)request.getAttribute(
285                            JavaConstants.JAVAX_PORTLET_PORTLET);
286    
287                    portletRequest = (PortletRequest)request.getAttribute(
288                            JavaConstants.JAVAX_PORTLET_REQUEST);
289                    portletResponse = (PortletResponse)request.getAttribute(
290                            JavaConstants.JAVAX_PORTLET_RESPONSE);
291    
292                    liferayPortletResponse = (LiferayPortletResponse)portletResponse;
293    
294                    lifecycle = GetterUtil.getString(
295                            (String)request.getAttribute(PortletRequest.LIFECYCLE_PHASE));
296    
297                    if (log.isDebugEnabled()) {
298                            log.debug("Lifecycle " + lifecycle);
299                    }
300    
301                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
302                            actionRequest = (ActionRequest)portletRequest;
303                            actionResponse = (ActionResponse)portletResponse;
304                    }
305                    else if (lifecycle.equals(PortletRequest.EVENT_PHASE)) {
306                            eventRequest = (EventRequest)portletRequest;
307                            eventResponse = (EventResponse)portletResponse;
308                    }
309                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
310                            mimeResponse = (MimeResponse)portletResponse;
311                            renderRequest = (RenderRequest)portletRequest;
312                            renderResponse = (RenderResponse)portletResponse;
313                    }
314                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
315                            mimeResponse = (MimeResponse)portletResponse;
316                            resourceRequest = (ResourceRequest)portletRequest;
317                            resourceResponse = (ResourceResponse)portletResponse;
318                    }
319            }
320    
321            protected void initServletVariables() {
322                    servletConfig = pageContext.getServletConfig();
323                    servletContext = pageContext.getServletContext();
324                    request = (HttpServletRequest)pageContext.getRequest();
325                    response = (HttpServletResponse)pageContext.getResponse();
326            }
327    
328            protected void initThemeDisplayVariables() {
329                    themeDisplay = (ThemeDisplay)request.getAttribute(
330                            WebKeys.THEME_DISPLAY);
331    
332                    company = themeDisplay.getCompany();
333                    user = themeDisplay.getUser();
334            }
335    
336            protected void redirectTo(PortletURL portletURL) {
337                    redirectTo(portletURL.toString());
338            }
339    
340            protected void redirectTo(String redirect) {
341                    if (!lifecycle.equals(PortletRequest.ACTION_PHASE)) {
342                            throw new IllegalArgumentException(
343                                    "redirectTo can only be called during the action phase");
344                    }
345    
346                    if (Validator.isNotNull(viewPath)) {
347                            throw new IllegalArgumentException(
348                                    "redirectTo cannot be called if render has been called");
349                    }
350    
351                    this.redirect = redirect;
352            }
353    
354            protected void render(String actionPath) {
355                    if (Validator.isNotNull(redirect)) {
356                            throw new IllegalArgumentException(
357                                    "render cannot be called if redirectTo has been called");
358                    }
359    
360                    viewPath = actionPath;
361            }
362    
363            protected void updateAttachedModel(BaseModel<?> baseModel)
364                    throws Exception {
365    
366                    if (!(baseModel instanceof AttachedModel)) {
367                            return;
368                    }
369    
370                    AttachedModel attachedModel = (AttachedModel)baseModel;
371    
372                    long classNameId = 0;
373    
374                    String className = ParamUtil.getString(request, "className");
375    
376                    if (Validator.isNotNull(className)) {
377                            classNameId = PortalUtil.getClassNameId(className);
378                    }
379    
380                    if (classNameId > 0) {
381                            attachedModel.setClassNameId(classNameId);
382                    }
383    
384                    long classPK = ParamUtil.getLong(request, "classPK");
385    
386                    attachedModel.setClassPK(classPK);
387            }
388    
389            protected void updateAuditedModel(BaseModel<?> baseModel) throws Exception {
390                    if (!(baseModel instanceof AuditedModel)) {
391                            return;
392                    }
393    
394                    AuditedModel auditedModel = (AuditedModel)baseModel;
395    
396                    if (baseModel.isNew()) {
397                            auditedModel.setCompanyId(company.getCompanyId());
398                            auditedModel.setUserId(user.getUserId());
399                            auditedModel.setUserName(user.getFullName());
400                            auditedModel.setCreateDate(new Date());
401                            auditedModel.setModifiedDate(auditedModel.getCreateDate());
402                    }
403                    else {
404                            auditedModel.setModifiedDate(new Date());
405                    }
406            }
407    
408            protected void updateGroupedModel(BaseModel<?> baseModel) throws Exception {
409                    if (!(baseModel instanceof GroupedModel) || !baseModel.isNew()) {
410                            return;
411                    }
412    
413                    GroupedModel groupedModel = (GroupedModel)baseModel;
414    
415                    groupedModel.setGroupId(themeDisplay.getScopeGroupId());
416            }
417    
418            protected void updateModel(BaseModel<?> baseModel) throws Exception {
419                    BeanPropertiesUtil.setProperties(baseModel, request);
420    
421                    if (baseModel.isNew()) {
422                            baseModel.setPrimaryKeyObj(CounterLocalServiceUtil.increment());
423                    }
424    
425                    updateAuditedModel(baseModel);
426                    updateGroupedModel(baseModel);
427                    updateAttachedModel(baseModel);
428    
429                    if (baseModel instanceof PersistedModel) {
430                            PersistedModel persistedModel = (PersistedModel)baseModel;
431    
432                            persistedModel.persist();
433                    }
434    
435                    if (indexer != null) {
436                            indexer.reindex(baseModel);
437                    }
438            }
439    
440            protected void writeJSON(Object json) throws Exception {
441                    if (actionResponse != null) {
442                            HttpServletResponse response = PortalUtil.getHttpServletResponse(
443                                    actionResponse);
444    
445                            response.setContentType(ContentTypes.TEXT_JAVASCRIPT);
446    
447                            ServletResponseUtil.write(response, json.toString());
448                    }
449                    else if (mimeResponse != null) {
450                            mimeResponse.setContentType(ContentTypes.TEXT_JAVASCRIPT);
451    
452                            PortletResponseUtil.write(mimeResponse, json.toString());
453                    }
454            }
455    
456            protected static final String CALLED_PROCESS_ACTION =
457                    "CALLED_PROCESS_ACTION";
458    
459            protected static final String VIEW_PATH = "VIEW_PATH";
460    
461            protected static Log log = LogFactoryUtil.getLog(
462                    BaseAlloyControllerImpl.class);
463    
464            protected String actionPath;
465            protected ActionRequest actionRequest;
466            protected ActionResponse actionResponse;
467            protected AlloyPortlet alloyPortlet;
468            protected ClassLoader classLoader;
469            protected Class<?> clazz;
470            protected Company company;
471            protected String controllerPath;
472            protected EventRequest eventRequest;
473            protected EventResponse eventResponse;
474            protected Indexer indexer;
475            protected String lifecycle;
476            protected LiferayPortletConfig liferayPortletConfig;
477            protected LiferayPortletResponse liferayPortletResponse;
478            protected Map<String, Method> methodsMap;
479            protected MimeResponse mimeResponse;
480            protected PageContext pageContext;
481            protected Portlet portlet;
482            protected PortletContext portletContext;
483            protected PortletRequest portletRequest;
484            protected PortletResponse portletResponse;
485            protected String redirect;
486            protected RenderRequest renderRequest;
487            protected RenderResponse renderResponse;
488            protected HttpServletRequest request;
489            protected ResourceRequest resourceRequest;
490            protected ResourceResponse resourceResponse;
491            protected HttpServletResponse response;
492            protected ServletConfig servletConfig;
493            protected ServletContext servletContext;
494            protected ThemeDisplay themeDisplay;
495            protected String viewPath;
496            protected User user;
497    
498    }