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