001    /**
002     * Copyright (c) 2000-2013 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.bean.ConstantsBeanFactoryUtil;
020    import com.liferay.portal.kernel.dao.search.SearchContainer;
021    import com.liferay.portal.kernel.language.LanguageUtil;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.messaging.Destination;
025    import com.liferay.portal.kernel.messaging.InvokerMessageListener;
026    import com.liferay.portal.kernel.messaging.MessageBus;
027    import com.liferay.portal.kernel.messaging.MessageBusUtil;
028    import com.liferay.portal.kernel.messaging.MessageListener;
029    import com.liferay.portal.kernel.messaging.SerialDestination;
030    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
031    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
032    import com.liferay.portal.kernel.portlet.PortletBag;
033    import com.liferay.portal.kernel.portlet.PortletBagPool;
034    import com.liferay.portal.kernel.portlet.PortletResponseUtil;
035    import com.liferay.portal.kernel.scheduler.CronText;
036    import com.liferay.portal.kernel.scheduler.CronTrigger;
037    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
038    import com.liferay.portal.kernel.scheduler.StorageType;
039    import com.liferay.portal.kernel.scheduler.Trigger;
040    import com.liferay.portal.kernel.search.Field;
041    import com.liferay.portal.kernel.search.Hits;
042    import com.liferay.portal.kernel.search.Indexer;
043    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
044    import com.liferay.portal.kernel.search.SearchContext;
045    import com.liferay.portal.kernel.search.SearchContextFactory;
046    import com.liferay.portal.kernel.search.Sort;
047    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
048    import com.liferay.portal.kernel.servlet.SessionMessages;
049    import com.liferay.portal.kernel.transaction.Isolation;
050    import com.liferay.portal.kernel.transaction.Propagation;
051    import com.liferay.portal.kernel.transaction.Transactional;
052    import com.liferay.portal.kernel.util.ArrayUtil;
053    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
054    import com.liferay.portal.kernel.util.ContentTypes;
055    import com.liferay.portal.kernel.util.GetterUtil;
056    import com.liferay.portal.kernel.util.JavaConstants;
057    import com.liferay.portal.kernel.util.ParamUtil;
058    import com.liferay.portal.kernel.util.ServiceBeanMethodInvocationFactoryUtil;
059    import com.liferay.portal.kernel.util.StringBundler;
060    import com.liferay.portal.kernel.util.StringPool;
061    import com.liferay.portal.kernel.util.Validator;
062    import com.liferay.portal.kernel.util.WebKeys;
063    import com.liferay.portal.model.AttachedModel;
064    import com.liferay.portal.model.AuditedModel;
065    import com.liferay.portal.model.BaseModel;
066    import com.liferay.portal.model.Company;
067    import com.liferay.portal.model.GroupedModel;
068    import com.liferay.portal.model.PersistedModel;
069    import com.liferay.portal.model.Portlet;
070    import com.liferay.portal.model.User;
071    import com.liferay.portal.theme.ThemeDisplay;
072    import com.liferay.portal.util.PortalUtil;
073    
074    import java.io.Serializable;
075    
076    import java.lang.reflect.Method;
077    
078    import java.util.Date;
079    import java.util.HashMap;
080    import java.util.List;
081    import java.util.Locale;
082    import java.util.Map;
083    import java.util.Set;
084    
085    import javax.portlet.ActionRequest;
086    import javax.portlet.ActionResponse;
087    import javax.portlet.EventRequest;
088    import javax.portlet.EventResponse;
089    import javax.portlet.MimeResponse;
090    import javax.portlet.PortletContext;
091    import javax.portlet.PortletRequest;
092    import javax.portlet.PortletRequestDispatcher;
093    import javax.portlet.PortletResponse;
094    import javax.portlet.PortletURL;
095    import javax.portlet.RenderRequest;
096    import javax.portlet.RenderResponse;
097    import javax.portlet.ResourceRequest;
098    import javax.portlet.ResourceResponse;
099    
100    import javax.servlet.ServletConfig;
101    import javax.servlet.ServletContext;
102    import javax.servlet.http.HttpServletRequest;
103    import javax.servlet.http.HttpServletResponse;
104    import javax.servlet.jsp.PageContext;
105    
106    /**
107     * @author Brian Wing Shun Chan
108     */
109    public abstract class BaseAlloyControllerImpl implements AlloyController {
110    
111            public static final String TOUCH =
112                    BaseAlloyControllerImpl.class.getName() + "#TOUCH#";
113    
114            @Override
115            public void afterPropertiesSet() {
116                    initClass();
117                    initServletVariables();
118                    initPortletVariables();
119                    initThemeDisplayVariables();
120                    initMethods();
121                    initPaths();
122                    initIndexer();
123                    initMessageListeners();
124            }
125    
126            @Override
127            public void execute() throws Exception {
128                    if (permissioned &&
129                            !AlloyPermission.contains(
130                                    themeDisplay.getPermissionChecker(),
131                                    themeDisplay.getScopeGroupId(), portlet.getRootPortletId(),
132                                    controllerPath, actionPath)) {
133    
134                            renderError(
135                                    "you-do-not-have-permission-to-access-the-requested-resource");
136                    }
137    
138                    Method method = getMethod(actionPath);
139    
140                    if (method == null) {
141                            if (log.isDebugEnabled()) {
142                                    log.debug("No method found for action " + actionPath);
143                            }
144                    }
145    
146                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
147                            Class<?> superClass = clazz.getSuperclass();
148    
149                            Method executeActionMethod = superClass.getDeclaredMethod(
150                                    "executeAction", new Class<?>[] {Method.class});
151    
152                            ServiceBeanMethodInvocationFactoryUtil.proceed(
153                                    this, BaseAlloyControllerImpl.class, executeActionMethod,
154                                    new Object[] {method}, new String[] {"transactionAdvice"});
155                    }
156                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
157                            executeRender(method);
158                    }
159                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
160                            executeResource(method);
161                    }
162            }
163    
164            @Override
165            public Portlet getPortlet() {
166                    return portlet;
167            }
168    
169            @Override
170            public HttpServletRequest getRequest() {
171                    return request;
172            }
173    
174            @Override
175            public ThemeDisplay getThemeDisplay() {
176                    return themeDisplay;
177            }
178    
179            @Override
180            public long increment() throws Exception {
181                    return CounterLocalServiceUtil.increment();
182            }
183    
184            @Override
185            public void setPageContext(PageContext pageContext) {
186                    this.pageContext = pageContext;
187            }
188    
189            @Override
190            public void updateModel(BaseModel<?> baseModel) throws Exception {
191                    BeanPropertiesUtil.setProperties(baseModel, request);
192    
193                    if (baseModel.isNew()) {
194                            baseModel.setPrimaryKeyObj(increment());
195                    }
196    
197                    updateAuditedModel(baseModel);
198                    updateGroupedModel(baseModel);
199                    updateAttachedModel(baseModel);
200    
201                    if (baseModel instanceof PersistedModel) {
202                            PersistedModel persistedModel = (PersistedModel)baseModel;
203    
204                            persistedModel.persist();
205                    }
206    
207                    if ((indexer != null) &&
208                            indexerClassName.equals(baseModel.getModelClassName())) {
209    
210                            indexer.reindex(baseModel);
211                    }
212                    else {
213                            Indexer baseModelIndexer = IndexerRegistryUtil.getIndexer(
214                                    baseModel.getModelClass());
215    
216                            if (baseModelIndexer != null) {
217                                    baseModelIndexer.reindex(baseModel);
218                            }
219                    }
220            }
221    
222            protected void addSuccessMessage() {
223                    String successMessage = ParamUtil.getString(
224                            portletRequest, "successMessage");
225    
226                    SessionMessages.add(portletRequest, "requestProcessed", successMessage);
227            }
228    
229            protected MessageListener buildControllerMessageListener() {
230                    return null;
231            }
232    
233            protected String buildIncludePath(String viewPath) {
234                    if (viewPath.equals(_VIEW_PATH_ERROR)) {
235                            return "/WEB-INF/jsp/".concat(
236                                    portlet.getFriendlyURLMapping()).concat("/views/error.jsp");
237                    }
238    
239                    StringBundler sb = new StringBundler(7);
240    
241                    sb.append("/WEB-INF/jsp/");
242                    sb.append(portlet.getFriendlyURLMapping());
243                    sb.append("/views/");
244                    sb.append(controllerPath);
245                    sb.append(StringPool.SLASH);
246                    sb.append(viewPath);
247                    sb.append(".jsp");
248    
249                    return sb.toString();
250            }
251    
252            protected Indexer buildIndexer() {
253                    return null;
254            }
255    
256            protected MessageListener buildSchedulerMessageListener() {
257                    return null;
258            }
259    
260            @Transactional(
261                    isolation = Isolation.PORTAL, propagation = Propagation.REQUIRES_NEW,
262                    rollbackFor = {Exception.class}
263            )
264            protected void executeAction(Method method) throws Exception {
265                    if (method != null) {
266                            method.invoke(this);
267                    }
268    
269                    actionRequest.setAttribute(
270                            CALLED_PROCESS_ACTION, Boolean.TRUE.toString());
271    
272                    if (Validator.isNotNull(viewPath)) {
273                            actionRequest.setAttribute(VIEW_PATH, viewPath);
274    
275                            PortalUtil.copyRequestParameters(actionRequest, actionResponse);
276                    }
277                    else if (Validator.isNotNull(redirect)) {
278                            actionResponse.sendRedirect(redirect);
279                    }
280            }
281    
282            protected void executeRender(Method method) throws Exception {
283                    boolean calledProcessAction = GetterUtil.getBoolean(
284                            (String)request.getAttribute(CALLED_PROCESS_ACTION));
285    
286                    if (!calledProcessAction) {
287                            if (method != null) {
288                                    method.invoke(this);
289                            }
290                    }
291    
292                    if (Validator.isNull(viewPath)) {
293                            viewPath = actionPath;
294                    }
295    
296                    String includePath = buildIncludePath(viewPath);
297    
298                    PortletRequestDispatcher portletRequestDispatcher =
299                            portletContext.getRequestDispatcher(includePath);
300    
301                    if (portletRequestDispatcher == null) {
302                            log.error(includePath + " is not a valid include");
303                    }
304                    else {
305                            portletRequestDispatcher.include(portletRequest, portletResponse);
306                    }
307    
308                    Boolean touch = (Boolean)portletContext.getAttribute(
309                            TOUCH + portlet.getRootPortletId());
310    
311                    if (touch != null) {
312                            return;
313                    }
314    
315                    String touchPath =
316                            "/WEB-INF/jsp/" + portlet.getFriendlyURLMapping() +
317                                    "/views/touch.jsp";
318    
319                    if (log.isDebugEnabled()) {
320                            log.debug(
321                                    "Touch " + portlet.getRootPortletId() + " by including " +
322                                            touchPath);
323                    }
324    
325                    portletContext.setAttribute(
326                            TOUCH + portlet.getRootPortletId(), Boolean.FALSE);
327    
328                    portletRequestDispatcher = portletContext.getRequestDispatcher(
329                            touchPath);
330    
331                    if (portletRequestDispatcher != null) {
332                            portletRequestDispatcher.include(portletRequest, portletResponse);
333                    }
334            }
335    
336            protected void executeResource(Method method) throws Exception {
337                    if (method != null) {
338                            method.invoke(this);
339                    }
340            }
341    
342            protected Object getConstantsBean(Class<?> clazz) {
343                    return ConstantsBeanFactoryUtil.getConstantsBean(clazz);
344            }
345    
346            protected String getControllerDestinationName() {
347                    return "liferay/alloy/controller/".concat(
348                            getMessageListenerGroupName());
349            }
350    
351            protected String getMessageListenerGroupName() {
352                    String rootPortletId = portlet.getRootPortletId();
353    
354                    return rootPortletId.concat(StringPool.SLASH).concat(controllerPath);
355            }
356    
357            protected Method getMethod(String methodName, Class<?>... parameterTypes) {
358                    String methodKey = getMethodKey(methodName, parameterTypes);
359    
360                    return methodsMap.get(methodKey);
361            }
362    
363            protected String getMethodKey(
364                    String methodName, Class<?>... parameterTypes) {
365    
366                    StringBundler sb = new StringBundler(parameterTypes.length * 2 + 2);
367    
368                    sb.append(methodName);
369                    sb.append(StringPool.POUND);
370    
371                    for (Class<?> parameterType : parameterTypes) {
372                            sb.append(parameterType.getName());
373                            sb.append(StringPool.POUND);
374                    }
375    
376                    return sb.toString();
377            }
378    
379            protected String getSchedulerDestinationName() {
380                    return "liferay/alloy/scheduler/".concat(getMessageListenerGroupName());
381            }
382    
383            protected String getSchedulerJobName() {
384                    return getMessageListenerGroupName();
385            }
386    
387            protected Trigger getSchedulerTrigger() {
388                    CronText cronText = new CronText(
389                            CalendarFactoryUtil.getCalendar(), CronText.DAILY_FREQUENCY, 1);
390    
391                    return new CronTrigger(
392                            getSchedulerJobName(), getMessageListenerGroupName(),
393                            cronText.toString());
394            }
395    
396            protected Map<String, Serializable> getSearchAttributes(
397                            Object... attributes)
398                    throws Exception {
399    
400                    Map<String, Serializable> attributesMap =
401                            new HashMap<String, Serializable>();
402    
403                    if ((attributes.length == 0) || ((attributes.length % 2) != 0)) {
404                            throw new Exception("Arguments length is not an even number");
405                    }
406    
407                    for (int i = 0; i < attributes.length; i += 2) {
408                            String name = String.valueOf(attributes[i]);
409    
410                            Serializable value = (Serializable)attributes[i + 1];
411    
412                            attributesMap.put(name, value);
413                    }
414    
415                    return attributesMap;
416            }
417    
418            protected long increment(String name) throws Exception {
419                    return CounterLocalServiceUtil.increment(name);
420            }
421    
422            protected void initClass() {
423                    clazz = getClass();
424                    classLoader = clazz.getClassLoader();
425            }
426    
427            protected void initIndexer() {
428                    indexer = buildIndexer();
429    
430                    if (indexer == null) {
431                            return;
432                    }
433    
434                    indexerClassName = indexer.getClassNames()[0];
435    
436                    Indexer existingIndexer = IndexerRegistryUtil.getIndexer(
437                            indexerClassName);
438    
439                    if ((existingIndexer != null) && (existingIndexer == indexer)) {
440                            BaseAlloyIndexer baseAlloyIndexer = (BaseAlloyIndexer)indexer;
441    
442                            alloyServiceInvoker = baseAlloyIndexer.getAlloyServiceInvoker();
443    
444                            return;
445                    }
446    
447                    alloyServiceInvoker = new AlloyServiceInvoker(indexerClassName);
448    
449                    BaseAlloyIndexer baseAlloyIndexer = (BaseAlloyIndexer)indexer;
450    
451                    baseAlloyIndexer.setAlloyServiceInvoker(alloyServiceInvoker);
452                    baseAlloyIndexer.setPortletId(portlet.getRootPortletId());
453    
454                    PortletBag portletBag = PortletBagPool.get(portlet.getPortletId());
455    
456                    List<Indexer> indexerInstances = portletBag.getIndexerInstances();
457    
458                    if (existingIndexer != null) {
459                            IndexerRegistryUtil.unregister(existingIndexer);
460    
461                            indexerInstances.remove(existingIndexer);
462                    }
463    
464                    IndexerRegistryUtil.register(indexer);
465    
466                    indexerInstances.add(indexer);
467            }
468    
469            protected void initMessageListener(
470                    String destinationName, MessageListener messageListener,
471                    boolean enableScheduler) {
472    
473                    MessageBus messageBus = MessageBusUtil.getMessageBus();
474    
475                    Destination destination = messageBus.getDestination(destinationName);
476    
477                    if (destination != null) {
478                            Set<MessageListener> messageListeners =
479                                    destination.getMessageListeners();
480    
481                            for (MessageListener curMessageListener : messageListeners) {
482                                    if (!(curMessageListener instanceof InvokerMessageListener)) {
483                                            continue;
484                                    }
485    
486                                    InvokerMessageListener invokerMessageListener =
487                                            (InvokerMessageListener)curMessageListener;
488    
489                                    curMessageListener =
490                                            invokerMessageListener.getMessageListener();
491    
492                                    if (messageListener == curMessageListener) {
493                                            return;
494                                    }
495    
496                                    Class<?> messageListenerClass = messageListener.getClass();
497    
498                                    String messageListenerClassName =
499                                            messageListenerClass.getName();
500    
501                                    Class<?> curMessageListenerClass =
502                                            curMessageListener.getClass();
503    
504                                    if (!messageListenerClassName.equals(
505                                                    curMessageListenerClass.getName())) {
506    
507                                            continue;
508                                    }
509    
510                                    try {
511                                            if (enableScheduler) {
512                                                    SchedulerEngineHelperUtil.unschedule(
513                                                            getSchedulerJobName(),
514                                                            getMessageListenerGroupName(),
515                                                            StorageType.MEMORY_CLUSTERED);
516                                            }
517    
518                                            MessageBusUtil.unregisterMessageListener(
519                                                    destinationName, curMessageListener);
520                                    }
521                                    catch (Exception e) {
522                                            log.error(e, e);
523                                    }
524    
525                                    break;
526                            }
527                    }
528                    else {
529                            SerialDestination serialDestination = new SerialDestination();
530    
531                            serialDestination.setName(destinationName);
532    
533                            serialDestination.open();
534    
535                            MessageBusUtil.addDestination(serialDestination);
536                    }
537    
538                    try {
539                            MessageBusUtil.registerMessageListener(
540                                    destinationName, messageListener);
541    
542                            if (enableScheduler) {
543                                    SchedulerEngineHelperUtil.schedule(
544                                            getSchedulerTrigger(), StorageType.MEMORY_CLUSTERED, null,
545                                            destinationName, null, 0);
546                            }
547                    }
548                    catch (Exception e) {
549                            log.error(e, e);
550                    }
551            }
552    
553            protected void initMessageListeners() {
554                    controllerMessageListener = buildControllerMessageListener();
555    
556                    if (controllerMessageListener != null) {
557                            initMessageListener(
558                                    getControllerDestinationName(), controllerMessageListener,
559                                    false);
560                    }
561    
562                    schedulerMessageListener = buildSchedulerMessageListener();
563    
564                    if (schedulerMessageListener != null) {
565                            initMessageListener(
566                                    getSchedulerDestinationName(), schedulerMessageListener, true);
567                    }
568            }
569    
570            protected void initMethods() {
571                    methodsMap = new HashMap<String, Method>();
572    
573                    Method[] methods = clazz.getMethods();
574    
575                    for (Method method : methods) {
576                            String methodKey = getMethodKey(
577                                    method.getName(), method.getParameterTypes());
578    
579                            methodsMap.put(methodKey, method);
580                    }
581            }
582    
583            protected void initPaths() {
584                    controllerPath = ParamUtil.getString(request, "controller");
585    
586                    if (Validator.isNull(controllerPath)) {
587                            Map<String, String> defaultRouteParameters =
588                                    alloyPortlet.getDefaultRouteParameters();
589    
590                            controllerPath = defaultRouteParameters.get("controller");
591                    }
592    
593                    if (log.isDebugEnabled()) {
594                            log.debug("Controller path " + controllerPath);
595                    }
596    
597                    actionPath = ParamUtil.getString(request, "action");
598    
599                    if (Validator.isNull(actionPath)) {
600                            Map<String, String> defaultRouteParameters =
601                                    alloyPortlet.getDefaultRouteParameters();
602    
603                            actionPath = defaultRouteParameters.get("action");
604                    }
605    
606                    if (log.isDebugEnabled()) {
607                            log.debug("Action path " + actionPath);
608                    }
609    
610                    viewPath = GetterUtil.getString(
611                            (String)request.getAttribute(VIEW_PATH));
612    
613                    request.removeAttribute(VIEW_PATH);
614    
615                    if (log.isDebugEnabled()) {
616                            log.debug("View path " + viewPath);
617                    }
618    
619                    if (mimeResponse != null) {
620                            portletURL = mimeResponse.createRenderURL();
621    
622                            portletURL.setParameter("action", actionPath);
623                            portletURL.setParameter("controller", controllerPath);
624                            portletURL.setParameter("format", "html");
625    
626                            if (log.isDebugEnabled()) {
627                                    log.debug("Portlet URL " + portletURL);
628                            }
629                    }
630            }
631    
632            protected void initPortletVariables() {
633                    liferayPortletConfig = (LiferayPortletConfig)request.getAttribute(
634                            JavaConstants.JAVAX_PORTLET_CONFIG);
635    
636                    portletContext = liferayPortletConfig.getPortletContext();
637    
638                    portlet = liferayPortletConfig.getPortlet();
639    
640                    alloyPortlet = (AlloyPortlet)request.getAttribute(
641                            JavaConstants.JAVAX_PORTLET_PORTLET);
642    
643                    alloyPortlet.registerAlloyController(this);
644    
645                    portletRequest = (PortletRequest)request.getAttribute(
646                            JavaConstants.JAVAX_PORTLET_REQUEST);
647                    portletResponse = (PortletResponse)request.getAttribute(
648                            JavaConstants.JAVAX_PORTLET_RESPONSE);
649    
650                    liferayPortletResponse = (LiferayPortletResponse)portletResponse;
651    
652                    lifecycle = GetterUtil.getString(
653                            (String)request.getAttribute(PortletRequest.LIFECYCLE_PHASE));
654    
655                    if (log.isDebugEnabled()) {
656                            log.debug("Lifecycle " + lifecycle);
657                    }
658    
659                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
660                            actionRequest = (ActionRequest)portletRequest;
661                            actionResponse = (ActionResponse)portletResponse;
662                    }
663                    else if (lifecycle.equals(PortletRequest.EVENT_PHASE)) {
664                            eventRequest = (EventRequest)portletRequest;
665                            eventResponse = (EventResponse)portletResponse;
666                    }
667                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
668                            mimeResponse = (MimeResponse)portletResponse;
669                            renderRequest = (RenderRequest)portletRequest;
670                            renderResponse = (RenderResponse)portletResponse;
671                    }
672                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
673                            mimeResponse = (MimeResponse)portletResponse;
674                            resourceRequest = (ResourceRequest)portletRequest;
675                            resourceResponse = (ResourceResponse)portletResponse;
676                    }
677            }
678    
679            protected void initServletVariables() {
680                    servletConfig = pageContext.getServletConfig();
681                    servletContext = pageContext.getServletContext();
682                    request = (HttpServletRequest)pageContext.getRequest();
683                    response = (HttpServletResponse)pageContext.getResponse();
684            }
685    
686            protected void initThemeDisplayVariables() {
687                    themeDisplay = (ThemeDisplay)request.getAttribute(
688                            WebKeys.THEME_DISPLAY);
689    
690                    company = themeDisplay.getCompany();
691                    locale = themeDisplay.getLocale();
692                    user = themeDisplay.getUser();
693            }
694    
695            protected void redirectTo(PortletURL portletURL) {
696                    redirectTo(portletURL.toString());
697            }
698    
699            protected void redirectTo(String redirect) {
700                    if (!lifecycle.equals(PortletRequest.ACTION_PHASE)) {
701                            throw new IllegalArgumentException(
702                                    "redirectTo can only be called during the action phase");
703                    }
704    
705                    if (Validator.isNotNull(viewPath)) {
706                            throw new IllegalArgumentException(
707                                    "redirectTo cannot be called if render has been called");
708                    }
709    
710                    this.redirect = redirect;
711            }
712    
713            protected void render(String actionPath) {
714                    if (Validator.isNotNull(redirect)) {
715                            throw new IllegalArgumentException(
716                                    "render cannot be called if redirectTo has been called");
717                    }
718    
719                    viewPath = actionPath;
720            }
721    
722            protected void renderError(String pattern, Object... arguments) {
723                    portletRequest.setAttribute("arguments", arguments);
724                    portletRequest.setAttribute("pattern", pattern);
725    
726                    render(_VIEW_PATH_ERROR);
727            }
728    
729            protected AlloySearchResult search(
730                            Map<String, Serializable> attributes, String keywords, Sort sort)
731                    throws Exception {
732    
733                    return search(attributes, keywords, new Sort[] {sort});
734            }
735    
736            protected AlloySearchResult search(
737                            Map<String, Serializable> attributes, String keywords, Sort[] sorts)
738                    throws Exception {
739    
740                    if (indexer == null) {
741                            throw new Exception("No indexer found for " + controllerPath);
742                    }
743    
744                    AlloySearchResult alloySearchResult = new AlloySearchResult();
745    
746                    alloySearchResult.setAlloyServiceInvoker(alloyServiceInvoker);
747    
748                    SearchContainer<BaseModel<?>> searchContainer =
749                            new SearchContainer<BaseModel<?>>(
750                                    portletRequest, portletURL, null, null);
751    
752                    SearchContext searchContext = SearchContextFactory.getInstance(request);
753    
754                    if ((attributes != null) && !attributes.isEmpty()) {
755                            searchContext.setAttributes(attributes);
756                    }
757    
758                    searchContext.setEnd(searchContainer.getEnd());
759    
760                    Class<?> indexerClass = Class.forName(indexerClassName);
761    
762                    try {
763                            indexerClass.getField(Field.GROUP_ID);
764                    }
765                    catch (Exception e) {
766                            searchContext.setGroupIds(null);
767                    }
768    
769                    if (Validator.isNotNull(keywords)) {
770                            searchContext.setKeywords(keywords);
771                    }
772    
773                    if (ArrayUtil.isNotEmpty(sorts)) {
774                            searchContext.setSorts(sorts);
775                    }
776    
777                    searchContext.setStart(searchContainer.getStart());
778    
779                    Hits hits = indexer.search(searchContext);
780    
781                    alloySearchResult.setHits(hits);
782    
783                    alloySearchResult.setPortletURL(portletURL);
784    
785                    alloySearchResult.afterPropertiesSet();
786    
787                    return alloySearchResult;
788            }
789    
790            protected AlloySearchResult search(String keywords) throws Exception {
791                    return search(keywords, (Sort[])null);
792            }
793    
794            protected AlloySearchResult search(String keywords, Sort sort)
795                    throws Exception {
796    
797                    return search(keywords, new Sort[] {sort});
798            }
799    
800            protected AlloySearchResult search(String keywords, Sort[] sorts)
801                    throws Exception {
802    
803                    return search(null, keywords, sorts);
804            }
805    
806            protected void setAlloyServiceInvokerClass(Class<?> clazz) {
807                    alloyServiceInvoker = new AlloyServiceInvoker(clazz.getName());
808            }
809    
810            protected void setPermissioned(boolean permissioned) {
811                    this.permissioned = permissioned;
812            }
813    
814            protected String translate(String pattern, Object... arguments) {
815                    return LanguageUtil.format(locale, pattern, arguments);
816            }
817    
818            protected void updateAttachedModel(BaseModel<?> baseModel)
819                    throws Exception {
820    
821                    if (!(baseModel instanceof AttachedModel)) {
822                            return;
823                    }
824    
825                    AttachedModel attachedModel = (AttachedModel)baseModel;
826    
827                    long classNameId = 0;
828    
829                    String className = ParamUtil.getString(request, "className");
830    
831                    if (Validator.isNotNull(className)) {
832                            classNameId = PortalUtil.getClassNameId(className);
833                    }
834    
835                    if (classNameId > 0) {
836                            attachedModel.setClassNameId(classNameId);
837                    }
838    
839                    long classPK = ParamUtil.getLong(request, "classPK");
840    
841                    if (classPK > 0) {
842                            attachedModel.setClassPK(classPK);
843                    }
844            }
845    
846            protected void updateAuditedModel(BaseModel<?> baseModel) throws Exception {
847                    if (!(baseModel instanceof AuditedModel)) {
848                            return;
849                    }
850    
851                    AuditedModel auditedModel = (AuditedModel)baseModel;
852    
853                    if (baseModel.isNew()) {
854                            auditedModel.setCompanyId(company.getCompanyId());
855                            auditedModel.setUserId(user.getUserId());
856                            auditedModel.setUserName(user.getFullName());
857                            auditedModel.setCreateDate(new Date());
858                            auditedModel.setModifiedDate(auditedModel.getCreateDate());
859                    }
860                    else {
861                            auditedModel.setModifiedDate(new Date());
862                    }
863            }
864    
865            protected void updateGroupedModel(BaseModel<?> baseModel) throws Exception {
866                    if (!(baseModel instanceof GroupedModel) || !baseModel.isNew()) {
867                            return;
868                    }
869    
870                    GroupedModel groupedModel = (GroupedModel)baseModel;
871    
872                    groupedModel.setGroupId(themeDisplay.getScopeGroupId());
873            }
874    
875            protected void writeJSON(Object json) throws Exception {
876                    if (actionResponse != null) {
877                            HttpServletResponse response = PortalUtil.getHttpServletResponse(
878                                    actionResponse);
879    
880                            response.setContentType(ContentTypes.APPLICATION_JSON);
881    
882                            ServletResponseUtil.write(response, json.toString());
883                    }
884                    else if (mimeResponse != null) {
885                            mimeResponse.setContentType(ContentTypes.APPLICATION_JSON);
886    
887                            PortletResponseUtil.write(mimeResponse, json.toString());
888                    }
889            }
890    
891            protected static final String CALLED_PROCESS_ACTION =
892                    BaseAlloyControllerImpl.class.getName() + "#CALLED_PROCESS_ACTION";
893    
894            protected static final String VIEW_PATH =
895                    BaseAlloyControllerImpl.class.getName() + "#VIEW_PATH";
896    
897            protected static Log log = LogFactoryUtil.getLog(
898                    BaseAlloyControllerImpl.class);
899    
900            protected String actionPath;
901            protected ActionRequest actionRequest;
902            protected ActionResponse actionResponse;
903            protected AlloyPortlet alloyPortlet;
904            protected AlloyServiceInvoker alloyServiceInvoker;
905            protected ClassLoader classLoader;
906            protected Class<?> clazz;
907            protected Company company;
908            protected MessageListener controllerMessageListener;
909            protected String controllerPath;
910            protected EventRequest eventRequest;
911            protected EventResponse eventResponse;
912            protected Indexer indexer;
913            protected String indexerClassName;
914            protected String lifecycle;
915            protected LiferayPortletConfig liferayPortletConfig;
916            protected LiferayPortletResponse liferayPortletResponse;
917            protected Locale locale;
918            protected Map<String, Method> methodsMap;
919            protected MimeResponse mimeResponse;
920            protected PageContext pageContext;
921            protected boolean permissioned;
922            protected Portlet portlet;
923            protected PortletContext portletContext;
924            protected PortletRequest portletRequest;
925            protected PortletResponse portletResponse;
926            protected PortletURL portletURL;
927            protected String redirect;
928            protected RenderRequest renderRequest;
929            protected RenderResponse renderResponse;
930            protected HttpServletRequest request;
931            protected ResourceRequest resourceRequest;
932            protected ResourceResponse resourceResponse;
933            protected HttpServletResponse response;
934            protected MessageListener schedulerMessageListener;
935            protected ServletConfig servletConfig;
936            protected ServletContext servletContext;
937            protected ThemeDisplay themeDisplay;
938            protected User user;
939            protected String viewPath;
940    
941            private static final String _VIEW_PATH_ERROR = "VIEW_PATH_ERROR";
942    
943    }