001    /**
002     * Copyright (c) 2000-2013 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.portal.layoutconfiguration.util.xml;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.portlet.PortletContainerUtil;
019    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
020    import com.liferay.portal.kernel.portlet.PortletParameterUtil;
021    import com.liferay.portal.kernel.servlet.BufferCacheServletResponse;
022    import com.liferay.portal.kernel.servlet.DynamicServletRequest;
023    import com.liferay.portal.kernel.util.AutoResetThreadLocal;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.PrefixPredicateFilter;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.kernel.xml.Document;
028    import com.liferay.portal.kernel.xml.Element;
029    import com.liferay.portal.kernel.xml.SAXReaderUtil;
030    import com.liferay.portal.model.Portlet;
031    import com.liferay.portal.model.PortletConstants;
032    import com.liferay.portal.service.PortletLocalServiceUtil;
033    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
034    import com.liferay.portal.theme.PortletDisplay;
035    import com.liferay.portal.theme.ThemeDisplay;
036    import com.liferay.portal.util.PortletKeys;
037    import com.liferay.portal.util.WebKeys;
038    import com.liferay.portlet.PortletPreferencesFactoryUtil;
039    
040    import java.util.HashMap;
041    import java.util.Map;
042    import java.util.Stack;
043    
044    import javax.servlet.RequestDispatcher;
045    import javax.servlet.ServletContext;
046    import javax.servlet.http.HttpServletRequest;
047    import javax.servlet.http.HttpServletResponse;
048    
049    /**
050     * @author Brian Wing Shun Chan
051     * @author Douglas Wong
052     */
053    public class PortletLogic extends RuntimeLogic {
054    
055            public static final String CLOSE_1_TAG = "</runtime-portlet>";
056    
057            public static final String CLOSE_2_TAG = "/>";
058    
059            public static final String OPEN_TAG = "<runtime-portlet";
060    
061            public PortletLogic(
062                    HttpServletRequest request, HttpServletResponse response) {
063    
064                    _request = request;
065                    _response = response;
066            }
067    
068            @Override
069            public String getClose1Tag() {
070                    return CLOSE_1_TAG;
071            }
072    
073            @Override
074            public String getOpenTag() {
075                    return OPEN_TAG;
076            }
077    
078            @Override
079            public String processXML(String xml) throws Exception {
080                    Document document = SAXReaderUtil.read(xml);
081    
082                    Element rootElement = document.getRootElement();
083    
084                    String portletId = rootElement.attributeValue("name");
085                    String instanceId = rootElement.attributeValue("instance");
086                    String queryString = rootElement.attributeValue("queryString");
087    
088                    if (Validator.isNotNull(instanceId)) {
089                            portletId = PortletConstants.assemblePortletId(
090                                    portletId, instanceId);
091                    }
092    
093                    BufferCacheServletResponse bufferCacheServletResponse =
094                            new BufferCacheServletResponse(_response);
095    
096                    queryString = PortletParameterUtil.addNamespace(portletId, queryString);
097    
098                    Map<String, String[]> parameterMap = _request.getParameterMap();
099    
100                    if (!portletId.equals(_request.getParameter("p_p_id"))) {
101                            parameterMap = MapUtil.filter(
102                                    parameterMap, new HashMap<String, String[]>(),
103                                    new PrefixPredicateFilter("p_p_"));
104                    }
105    
106                    HttpServletRequest request = DynamicServletRequest.addQueryString(
107                            _request, parameterMap, queryString, false);
108    
109                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
110                            WebKeys.THEME_DISPLAY);
111    
112                    Portlet portlet = getPortlet(themeDisplay, portletId);
113    
114                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
115    
116                    Stack<String> embeddedPortletIds = _embeddedPortletIds.get();
117    
118                    if (embeddedPortletIds == null) {
119                            embeddedPortletIds = new Stack<String>();
120    
121                            _embeddedPortletIds.set(embeddedPortletIds);
122                    }
123    
124                    if (embeddedPortletIds.search(portletDisplay.getId()) >
125                                    -1) {
126    
127                            String errorMessage = LanguageUtil.get(
128                                    themeDisplay.getLocale(),
129                                    "the-application-cannot-include-itself");
130    
131                            request.setAttribute(
132                                    "liferay-portlet:runtime:errorMessage", errorMessage);
133    
134                            ServletContext servletContext =
135                                    (ServletContext)request.getAttribute(WebKeys.CTX);
136    
137                            RequestDispatcher requestDispatcher =
138                                    servletContext.getRequestDispatcher(_ERROR_PAGE);
139    
140                            requestDispatcher.include(request, bufferCacheServletResponse);
141    
142                            return bufferCacheServletResponse.getString();
143                    }
144    
145                    embeddedPortletIds.push(portletId);
146    
147                    PortletContainerUtil.render(
148                            request, bufferCacheServletResponse, portlet);
149    
150                    embeddedPortletIds.pop();
151    
152                    return bufferCacheServletResponse.getString();
153            }
154    
155            /**
156             * @see com.liferay.portal.model.impl.LayoutTypePortletImpl#getStaticPortlets(
157             *      String)
158             */
159            protected Portlet getPortlet(ThemeDisplay themeDisplay, String portletId)
160                    throws Exception {
161    
162                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
163                            themeDisplay.getCompanyId(), portletId);
164    
165                    // See LayoutTypePortletImpl#getStaticPortlets for why we only clone
166                    // non-instanceable portlets
167    
168                    if (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
169                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, themeDisplay.getPlid(),
170                                    portletId) < 1) {
171    
172                            PortletPreferencesFactoryUtil.getPortletSetup(_request, portletId);
173    
174                            PortletLayoutListener portletLayoutListener =
175                                    portlet.getPortletLayoutListenerInstance();
176    
177                            if (portletLayoutListener != null) {
178                                    portletLayoutListener.onAddToLayout(
179                                            portletId, themeDisplay.getPlid());
180                            }
181                    }
182    
183                    if (!portlet.isInstanceable()) {
184                            portlet = (Portlet)portlet.clone();
185                    }
186    
187                    portlet.setStatic(true);
188    
189                    return portlet;
190            }
191    
192            private static final String _ERROR_PAGE =
193                    "/html/taglib/portlet/runtime/error.jsp";
194    
195            private static final ThreadLocal<Stack<String>> _embeddedPortletIds =
196                    new AutoResetThreadLocal<Stack<String>>(
197                            PortletLogic.class + "._embeddedPortletIds");
198    
199            private HttpServletRequest _request;
200            private HttpServletResponse _response;
201    
202    }