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