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