001    /**
002     * Copyright (c) 2000-present 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.portlet;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
021    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
022    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
023    import com.liferay.portal.kernel.portlet.LiferayWindowState;
024    import com.liferay.portal.kernel.portlet.PortletModeFactory;
025    import com.liferay.portal.kernel.portlet.PortletProvider;
026    import com.liferay.portal.kernel.portlet.PortletProviderUtil;
027    import com.liferay.portal.kernel.portlet.WindowStateFactory;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.Base64;
030    import com.liferay.portal.kernel.util.CharPool;
031    import com.liferay.portal.kernel.util.CookieKeys;
032    import com.liferay.portal.kernel.util.GetterUtil;
033    import com.liferay.portal.kernel.util.HtmlUtil;
034    import com.liferay.portal.kernel.util.Http;
035    import com.liferay.portal.kernel.util.HttpUtil;
036    import com.liferay.portal.kernel.util.MapUtil;
037    import com.liferay.portal.kernel.util.ParamUtil;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.util.WebKeys;
042    import com.liferay.portal.kernel.xml.QName;
043    import com.liferay.portal.model.Company;
044    import com.liferay.portal.model.Layout;
045    import com.liferay.portal.model.LayoutTypePortlet;
046    import com.liferay.portal.model.Portlet;
047    import com.liferay.portal.model.PortletApp;
048    import com.liferay.portal.model.PublicRenderParameter;
049    import com.liferay.portal.model.impl.VirtualLayout;
050    import com.liferay.portal.security.auth.AuthTokenUtil;
051    import com.liferay.portal.security.auth.AuthTokenWhitelistUtil;
052    import com.liferay.portal.security.lang.DoPrivilegedUtil;
053    import com.liferay.portal.service.LayoutLocalServiceUtil;
054    import com.liferay.portal.service.PortletLocalServiceUtil;
055    import com.liferay.portal.theme.PortletDisplay;
056    import com.liferay.portal.theme.ThemeDisplay;
057    import com.liferay.portal.util.PortalUtil;
058    import com.liferay.portal.util.PropsValues;
059    import com.liferay.portlet.admin.util.PortalProductMenuApplicationType;
060    import com.liferay.portlet.social.util.FacebookUtil;
061    import com.liferay.util.Encryptor;
062    import com.liferay.util.EncryptorException;
063    
064    import java.io.IOException;
065    import java.io.Serializable;
066    import java.io.UnsupportedEncodingException;
067    import java.io.Writer;
068    
069    import java.security.Key;
070    import java.security.PrivilegedAction;
071    
072    import java.util.Collections;
073    import java.util.LinkedHashMap;
074    import java.util.LinkedHashSet;
075    import java.util.Map;
076    import java.util.Set;
077    
078    import javax.portlet.PortletMode;
079    import javax.portlet.PortletModeException;
080    import javax.portlet.PortletRequest;
081    import javax.portlet.PortletURL;
082    import javax.portlet.ResourceRequest;
083    import javax.portlet.ResourceURL;
084    import javax.portlet.WindowState;
085    import javax.portlet.WindowStateException;
086    
087    import javax.servlet.http.HttpServletRequest;
088    
089    /**
090     * @author Brian Wing Shun Chan
091     * @author Jorge Ferrer
092     * @author Connor McKay
093     */
094    public class PortletURLImpl
095            implements LiferayPortletURL, PortletURL, ResourceURL, Serializable {
096    
097            public PortletURLImpl(
098                    HttpServletRequest request, String portletId, Layout layout,
099                    String lifecycle) {
100    
101                    this(request, portletId, null, layout.getPlid(), lifecycle);
102    
103                    _layout = layout;
104            }
105    
106            public PortletURLImpl(
107                    HttpServletRequest request, String portletId, long plid,
108                    String lifecycle) {
109    
110                    this(request, portletId, null, plid, lifecycle);
111            }
112    
113            public PortletURLImpl(
114                    PortletRequest portletRequest, String portletId, Layout layout,
115                    String lifecycle) {
116    
117                    this(
118                            PortalUtil.getHttpServletRequest(portletRequest), portletId,
119                            portletRequest, layout.getPlid(), lifecycle);
120    
121                    _layout = layout;
122            }
123    
124            public PortletURLImpl(
125                    PortletRequest portletRequest, String portletId, long plid,
126                    String lifecycle) {
127    
128                    this(
129                            PortalUtil.getHttpServletRequest(portletRequest), portletId,
130                            portletRequest, plid, lifecycle);
131            }
132    
133            @Override
134            public void addParameterIncludedInPath(String name) {
135                    _parametersIncludedInPath.add(name);
136            }
137    
138            @Override
139            public void addProperty(String key, String value) {
140                    if (key == null) {
141                            throw new IllegalArgumentException();
142                    }
143            }
144    
145            @Override
146            public String getCacheability() {
147                    return _cacheability;
148            }
149    
150            public HttpServletRequest getHttpServletRequest() {
151                    return _request;
152            }
153    
154            public Layout getLayout() {
155                    if (_layout == null) {
156                            try {
157                                    if (_plid > 0) {
158                                            _layout = LayoutLocalServiceUtil.getLayout(_plid);
159                                    }
160                            }
161                            catch (Exception e) {
162                                    if (_log.isWarnEnabled()) {
163                                            _log.warn("Layout cannot be found for " + _plid);
164                                    }
165                            }
166                    }
167    
168                    return _layout;
169            }
170    
171            public String getLayoutFriendlyURL() {
172                    return _layoutFriendlyURL;
173            }
174    
175            @Override
176            public String getLifecycle() {
177                    return _lifecycle;
178            }
179    
180            public String getNamespace() {
181                    if (_namespace == null) {
182                            _namespace = PortalUtil.getPortletNamespace(_portletId);
183                    }
184    
185                    return _namespace;
186            }
187    
188            @Override
189            public String getParameter(String name) {
190                    String[] values = _params.get(name);
191    
192                    if (ArrayUtil.isNotEmpty(values)) {
193                            return values[0];
194                    }
195                    else {
196                            return null;
197                    }
198            }
199    
200            @Override
201            public Map<String, String[]> getParameterMap() {
202                    return _params;
203            }
204    
205            @Override
206            public Set<String> getParametersIncludedInPath() {
207                    return _parametersIncludedInPath;
208            }
209    
210            public long getPlid() {
211                    return _plid;
212            }
213    
214            public Portlet getPortlet() {
215                    if (_portlet == null) {
216                            try {
217                                    _portlet = PortletLocalServiceUtil.getPortletById(
218                                            PortalUtil.getCompanyId(_request), _portletId);
219                            }
220                            catch (SystemException se) {
221                                    _log.error(se.getMessage());
222                            }
223                    }
224    
225                    return _portlet;
226            }
227    
228            public String getPortletFriendlyURLPath() {
229                    String portletFriendlyURLPath = null;
230    
231                    Portlet portlet = getPortlet();
232    
233                    if (portlet != null) {
234                            if (portlet.isUndeployedPortlet()) {
235                                    return portletFriendlyURLPath;
236                            }
237    
238                            FriendlyURLMapper friendlyURLMapper =
239                                    portlet.getFriendlyURLMapperInstance();
240    
241                            if (friendlyURLMapper != null) {
242                                    portletFriendlyURLPath = friendlyURLMapper.buildPath(this);
243    
244                                    if (_log.isDebugEnabled()) {
245                                            _log.debug(
246                                                    "Portlet friendly URL path " + portletFriendlyURLPath);
247                                    }
248                            }
249                    }
250    
251                    return portletFriendlyURLPath;
252            }
253    
254            @Override
255            public String getPortletId() {
256                    return _portletId;
257            }
258    
259            @Override
260            public PortletMode getPortletMode() {
261                    if (_portletModeString == null) {
262                            return null;
263                    }
264    
265                    return PortletModeFactory.getPortletMode(_portletModeString);
266            }
267    
268            public PortletRequest getPortletRequest() {
269                    return _portletRequest;
270            }
271    
272            @Override
273            public Set<String> getRemovedParameterNames() {
274                    return _removedParameterNames;
275            }
276    
277            @Override
278            public Map<String, String> getReservedParameterMap() {
279                    if (_reservedParameters != null) {
280                            return _reservedParameters;
281                    }
282    
283                    _reservedParameters = new LinkedHashMap<>();
284    
285                    _reservedParameters.put("p_p_id", _portletId);
286    
287                    if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
288                            _reservedParameters.put("p_p_lifecycle", "1");
289                    }
290                    else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
291                            _reservedParameters.put("p_p_lifecycle", "0");
292                    }
293                    else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
294                            _reservedParameters.put("p_p_lifecycle", "2");
295                    }
296    
297                    if (_windowStateString != null) {
298                            _reservedParameters.put("p_p_state", _windowStateString);
299                    }
300    
301                    if (_windowStateRestoreCurrentView) {
302                            _reservedParameters.put("p_p_state_rcv", "1");
303                    }
304    
305                    if (_portletModeString != null) {
306                            _reservedParameters.put("p_p_mode", _portletModeString);
307                    }
308    
309                    if (_resourceID != null) {
310                            _reservedParameters.put("p_p_resource_id", _resourceID);
311                    }
312    
313                    if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
314                            _reservedParameters.put("p_p_cacheability", _cacheability);
315                    }
316    
317                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
318                            WebKeys.THEME_DISPLAY);
319    
320                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
321    
322                    if (Validator.isNotNull(portletDisplay.getColumnId())) {
323                            _reservedParameters.put("p_p_col_id", portletDisplay.getColumnId());
324                    }
325    
326                    if (portletDisplay.getColumnPos() > 0) {
327                            _reservedParameters.put(
328                                    "p_p_col_pos", String.valueOf(portletDisplay.getColumnPos()));
329                    }
330    
331                    if (portletDisplay.getColumnCount() > 0) {
332                            _reservedParameters.put(
333                                    "p_p_col_count",
334                                    String.valueOf(portletDisplay.getColumnCount()));
335                    }
336    
337                    _reservedParameters = Collections.unmodifiableMap(_reservedParameters);
338    
339                    return _reservedParameters;
340            }
341    
342            @Override
343            public String getResourceID() {
344                    return _resourceID;
345            }
346    
347            @Override
348            public WindowState getWindowState() {
349                    if (_windowStateString == null) {
350                            return null;
351                    }
352    
353                    return WindowStateFactory.getWindowState(_windowStateString);
354            }
355    
356            @Override
357            public boolean isAnchor() {
358                    return _anchor;
359            }
360    
361            @Override
362            public boolean isCopyCurrentRenderParameters() {
363                    return _copyCurrentRenderParameters;
364            }
365    
366            @Override
367            public boolean isEncrypt() {
368                    return _encrypt;
369            }
370    
371            @Override
372            public boolean isEscapeXml() {
373                    return _escapeXml;
374            }
375    
376            @Override
377            public boolean isParameterIncludedInPath(String name) {
378                    if (_parametersIncludedInPath.contains(name)) {
379                            return true;
380                    }
381                    else {
382                            return false;
383                    }
384            }
385    
386            @Override
387            public boolean isSecure() {
388                    return _secure;
389            }
390    
391            @Override
392            public void removePublicRenderParameter(String name) {
393                    if (name == null) {
394                            throw new IllegalArgumentException();
395                    }
396    
397                    Portlet portlet = getPortlet();
398    
399                    if (portlet == null) {
400                            return;
401                    }
402    
403                    PublicRenderParameter publicRenderParameter =
404                            portlet.getPublicRenderParameter(name);
405    
406                    if (publicRenderParameter == null) {
407                            if (_log.isWarnEnabled()) {
408                                    _log.warn("Public parameter " + name + "does not exist");
409                            }
410    
411                            return;
412                    }
413    
414                    QName qName = publicRenderParameter.getQName();
415    
416                    _removePublicRenderParameters.put(
417                            PortletQNameUtil.getRemovePublicRenderParameterName(qName),
418                            new String[] {"1"});
419            }
420    
421            @Override
422            public void setAnchor(boolean anchor) {
423                    _anchor = anchor;
424    
425                    clearCache();
426            }
427    
428            @Override
429            public void setCacheability(String cacheability) {
430                    if (cacheability == null) {
431                            throw new IllegalArgumentException("Cacheability is null");
432                    }
433    
434                    if (!cacheability.equals(FULL) && !cacheability.equals(PORTLET) &&
435                            !cacheability.equals(PAGE)) {
436    
437                            throw new IllegalArgumentException(
438                                    "Cacheability " + cacheability + " is not " + FULL + ", " +
439                                            PORTLET + ", or " + PAGE);
440                    }
441    
442                    if (_portletRequest instanceof ResourceRequest) {
443                            ResourceRequest resourceRequest = (ResourceRequest)_portletRequest;
444    
445                            String parentCacheability = resourceRequest.getCacheability();
446    
447                            if (parentCacheability.equals(FULL)) {
448                                    if (!cacheability.equals(FULL)) {
449                                            throw new IllegalStateException(
450                                                    "Unable to set a weaker cacheability " + cacheability);
451                                    }
452                            }
453                            else if (parentCacheability.equals(PORTLET)) {
454                                    if (!cacheability.equals(FULL) &&
455                                            !cacheability.equals(PORTLET)) {
456    
457                                            throw new IllegalStateException(
458                                                    "Unable to set a weaker cacheability " + cacheability);
459                                    }
460                            }
461                    }
462    
463                    _cacheability = cacheability;
464    
465                    clearCache();
466            }
467    
468            @Override
469            public void setCopyCurrentRenderParameters(
470                    boolean copyCurrentRenderParameters) {
471    
472                    _copyCurrentRenderParameters = copyCurrentRenderParameters;
473            }
474    
475            @Override
476            public void setDoAsGroupId(long doAsGroupId) {
477                    _doAsGroupId = doAsGroupId;
478    
479                    clearCache();
480            }
481    
482            @Override
483            public void setDoAsUserId(long doAsUserId) {
484                    _doAsUserId = doAsUserId;
485    
486                    clearCache();
487            }
488    
489            @Override
490            public void setDoAsUserLanguageId(String doAsUserLanguageId) {
491                    _doAsUserLanguageId = doAsUserLanguageId;
492    
493                    clearCache();
494            }
495    
496            @Override
497            public void setEncrypt(boolean encrypt) {
498                    _encrypt = encrypt;
499    
500                    clearCache();
501            }
502    
503            @Override
504            public void setEscapeXml(boolean escapeXml) {
505                    _escapeXml = escapeXml;
506    
507                    clearCache();
508            }
509    
510            @Override
511            public void setLifecycle(String lifecycle) {
512                    _lifecycle = lifecycle;
513    
514                    clearCache();
515            }
516    
517            @Override
518            public void setParameter(String name, String value) {
519                    setParameter(name, value, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
520            }
521    
522            @Override
523            public void setParameter(String name, String value, boolean append) {
524                    if (name == null) {
525                            throw new IllegalArgumentException();
526                    }
527    
528                    if (value == null) {
529                            removeParameter(name);
530    
531                            return;
532                    }
533    
534                    setParameter(name, new String[] {value}, append);
535            }
536    
537            @Override
538            public void setParameter(String name, String[] values) {
539                    setParameter(name, values, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
540            }
541    
542            @Override
543            public void setParameter(String name, String[] values, boolean append) {
544                    if ((name == null) || (values == null)) {
545                            throw new IllegalArgumentException();
546                    }
547    
548                    for (String value : values) {
549                            if (value == null) {
550                                    throw new IllegalArgumentException();
551                            }
552                    }
553    
554                    if (!append) {
555                            _params.put(name, values);
556                    }
557                    else {
558                            String[] oldValues = _params.get(name);
559    
560                            if (oldValues == null) {
561                                    _params.put(name, values);
562                            }
563                            else {
564                                    String[] newValues = ArrayUtil.append(oldValues, values);
565    
566                                    _params.put(name, newValues);
567                            }
568                    }
569    
570                    clearCache();
571            }
572    
573            @Override
574            public void setParameters(Map<String, String[]> params) {
575                    if (params == null) {
576                            throw new IllegalArgumentException();
577                    }
578                    else {
579                            Map<String, String[]> newParams = new LinkedHashMap<>();
580    
581                            for (Map.Entry<String, String[]> entry : params.entrySet()) {
582                                    try {
583                                            String key = entry.getKey();
584                                            String[] value = entry.getValue();
585    
586                                            if (key == null) {
587                                                    throw new IllegalArgumentException();
588                                            }
589                                            else if (value == null) {
590                                                    throw new IllegalArgumentException();
591                                            }
592    
593                                            newParams.put(key, value);
594                                    }
595                                    catch (ClassCastException cce) {
596                                            throw new IllegalArgumentException(cce);
597                                    }
598                            }
599    
600                            _params = newParams;
601                    }
602    
603                    clearCache();
604            }
605    
606            @Override
607            public void setPlid(long plid) {
608                    _plid = plid;
609    
610                    clearCache();
611            }
612    
613            @Override
614            public void setPortletId(String portletId) {
615                    _portletId = portletId;
616    
617                    clearCache();
618            }
619    
620            @Override
621            public void setPortletMode(PortletMode portletMode)
622                    throws PortletModeException {
623    
624                    if (_portletRequest != null) {
625                            Portlet portlet = getPortlet();
626    
627                            if ((portlet != null) &&
628                                    !portlet.hasPortletMode(
629                                            _portletRequest.getResponseContentType(), portletMode)) {
630    
631                                    throw new PortletModeException(
632                                            portletMode.toString(), portletMode);
633                            }
634                    }
635    
636                    _portletModeString = portletMode.toString();
637    
638                    clearCache();
639            }
640    
641            public void setPortletMode(String portletMode) throws PortletModeException {
642                    setPortletMode(PortletModeFactory.getPortletMode(portletMode));
643            }
644    
645            @Override
646            public void setProperty(String key, String value) {
647                    if (key == null) {
648                            throw new IllegalArgumentException();
649                    }
650            }
651    
652            @Override
653            public void setRefererGroupId(long refererGroupId) {
654                    _refererGroupId = refererGroupId;
655    
656                    clearCache();
657            }
658    
659            @Override
660            public void setRefererPlid(long refererPlid) {
661                    _refererPlid = refererPlid;
662    
663                    clearCache();
664            }
665    
666            @Override
667            public void setRemovedParameterNames(Set<String> removedParameterNames) {
668                    _removedParameterNames = removedParameterNames;
669    
670                    clearCache();
671            }
672    
673            @Override
674            public void setResourceID(String resourceID) {
675                    _resourceID = resourceID;
676            }
677    
678            @Override
679            public void setSecure(boolean secure) {
680                    _secure = secure;
681    
682                    clearCache();
683            }
684    
685            public void setWindowState(String windowState) throws WindowStateException {
686                    setWindowState(WindowStateFactory.getWindowState(windowState));
687            }
688    
689            @Override
690            public void setWindowState(WindowState windowState)
691                    throws WindowStateException {
692    
693                    if (_portletRequest != null) {
694                            if (!_portletRequest.isWindowStateAllowed(windowState)) {
695                                    throw new WindowStateException(
696                                            windowState.toString(), windowState);
697                            }
698                    }
699    
700                    if (LiferayWindowState.isWindowStatePreserved(
701                                    getWindowState(), windowState)) {
702    
703                            _windowStateString = windowState.toString();
704                    }
705    
706                    clearCache();
707            }
708    
709            public void setWindowStateRestoreCurrentView(
710                    boolean windowStateRestoreCurrentView) {
711    
712                    _windowStateRestoreCurrentView = windowStateRestoreCurrentView;
713            }
714    
715            @Override
716            public String toString() {
717                    if (_toString != null) {
718                            return _toString;
719                    }
720    
721                    _toString = DoPrivilegedUtil.wrap(new ToStringPrivilegedAction());
722    
723                    return _toString;
724            }
725    
726            @Override
727            public void write(Writer writer) throws IOException {
728                    write(writer, _escapeXml);
729            }
730    
731            @Override
732            public void write(Writer writer, boolean escapeXml) throws IOException {
733                    String toString = toString();
734    
735                    if (escapeXml && !_escapeXml) {
736                            toString = HtmlUtil.escape(toString);
737                    }
738    
739                    writer.write(toString);
740            }
741    
742            protected PortletURLImpl(
743                    HttpServletRequest request, String portletId,
744                    PortletRequest portletRequest, long plid, String lifecycle) {
745    
746                    _request = request;
747                    _portletId = portletId;
748                    _portletRequest = portletRequest;
749                    _plid = plid;
750                    _lifecycle = lifecycle;
751                    _parametersIncludedInPath = new LinkedHashSet<>();
752                    _params = new LinkedHashMap<>();
753                    _removePublicRenderParameters = new LinkedHashMap<>();
754                    _secure = PortalUtil.isSecure(request);
755                    _wsrp = ParamUtil.getBoolean(request, "wsrp");
756    
757                    Portlet portlet = getPortlet();
758    
759                    if (portlet != null) {
760                            Set<String> autopropagatedParameters =
761                                    portlet.getAutopropagatedParameters();
762    
763                            for (String autopropagatedParameter : autopropagatedParameters) {
764                                    if (PortalUtil.isReservedParameter(autopropagatedParameter)) {
765                                            continue;
766                                    }
767    
768                                    String value = request.getParameter(autopropagatedParameter);
769    
770                                    if (value != null) {
771                                            setParameter(autopropagatedParameter, value);
772                                    }
773                            }
774    
775                            PortletApp portletApp = portlet.getPortletApp();
776    
777                            _escapeXml = MapUtil.getBoolean(
778                                    portletApp.getContainerRuntimeOptions(),
779                                    LiferayPortletConfig.RUNTIME_OPTION_ESCAPE_XML,
780                                    PropsValues.PORTLET_URL_ESCAPE_XML);
781                    }
782    
783                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
784    
785                    if ((layout != null) && (layout.getPlid() == _plid) &&
786                            (layout instanceof VirtualLayout)) {
787    
788                            _layout = layout;
789                    }
790            }
791    
792            protected void addPortalAuthToken(StringBundler sb, Key key) {
793                    if (!PropsValues.AUTH_TOKEN_CHECK_ENABLED ||
794                            !_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
795    
796                            return;
797                    }
798    
799                    Portlet portlet = getPortlet();
800    
801                    if (portlet == null) {
802                            return;
803                    }
804    
805                    String strutsAction = getParameter("struts_action");
806    
807                    if (AuthTokenWhitelistUtil.isPortletCSRFWhitelisted(
808                                    portlet.getCompanyId(), _portletId, strutsAction)) {
809    
810                            return;
811                    }
812    
813                    sb.append("p_auth");
814                    sb.append(StringPool.EQUAL);
815                    sb.append(processValue(key, AuthTokenUtil.getToken(_request)));
816                    sb.append(StringPool.AMPERSAND);
817            }
818    
819            protected void addPortletAuthToken(StringBundler sb, Key key) {
820                    if (!PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED) {
821                            return;
822                    }
823    
824                    Portlet portlet = getPortlet();
825    
826                    if (portlet == null) {
827                            return;
828                    }
829    
830                    if (!portlet.isAddDefaultResource()) {
831                            return;
832                    }
833    
834                    String strutsAction = getParameter("struts_action");
835    
836                    if (AuthTokenWhitelistUtil.isPortletInvocationWhitelisted(
837                                    portlet.getCompanyId(), _portletId, strutsAction)) {
838    
839                            return;
840                    }
841    
842                    try {
843                            LayoutTypePortlet targetLayoutTypePortlet =
844                                    (LayoutTypePortlet)getLayout().getLayoutType();
845    
846                            if (targetLayoutTypePortlet.hasPortletId(_portletId)) {
847                                    return;
848                            }
849                    }
850                    catch (Exception e) {
851                            if (_log.isDebugEnabled()) {
852                                    _log.debug(e.getMessage(), e);
853                            }
854                    }
855    
856                    String controlPanelMenuPortletId = PortletProviderUtil.getPortletId(
857                            PortalProductMenuApplicationType.ProductMenu.CLASS_NAME,
858                            PortletProvider.Action.VIEW);
859    
860                    if (_portletId.equals(controlPanelMenuPortletId)) {
861                            return;
862                    }
863    
864                    sb.append("p_p_auth");
865                    sb.append(StringPool.EQUAL);
866                    sb.append(
867                            processValue(
868                                    key, AuthTokenUtil.getToken(_request, _plid, _portletId)));
869                    sb.append(StringPool.AMPERSAND);
870            }
871    
872            protected void clearCache() {
873                    _reservedParameters = null;
874                    _toString = null;
875            }
876    
877            protected String generateToString() {
878                    StringBundler sb = new StringBundler(64);
879    
880                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
881                            WebKeys.THEME_DISPLAY);
882    
883                    if (themeDisplay == null) {
884                            if (_log.isWarnEnabled()) {
885                                    _log.warn(
886                                            "Unable to generate string because theme display is null");
887                            }
888    
889                            return StringPool.BLANK;
890                    }
891    
892                    String portalURL = null;
893    
894                    if (themeDisplay.isFacebook()) {
895                            portalURL =
896                                    FacebookUtil.FACEBOOK_APPS_URL +
897                                            themeDisplay.getFacebookCanvasPageURL();
898                    }
899                    else {
900                            portalURL = PortalUtil.getPortalURL(_request, _secure);
901                    }
902    
903                    try {
904                            if (_layoutFriendlyURL == null) {
905                                    Layout layout = getLayout();
906    
907                                    if (layout != null) {
908                                            _layoutFriendlyURL = GetterUtil.getString(
909                                                    PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
910    
911                                            if (_secure) {
912                                                    _layoutFriendlyURL = HttpUtil.protocolize(
913                                                            _layoutFriendlyURL,
914                                                            PropsValues.WEB_SERVER_HTTPS_PORT, true);
915                                            }
916                                    }
917                            }
918                    }
919                    catch (Exception e) {
920                            _log.error(e);
921                    }
922    
923                    Key key = null;
924    
925                    try {
926                            if (_encrypt) {
927                                    Company company = PortalUtil.getCompany(_request);
928    
929                                    key = company.getKeyObj();
930                            }
931                    }
932                    catch (Exception e) {
933                            _log.error(e);
934                    }
935    
936                    if (Validator.isNull(_layoutFriendlyURL)) {
937                            sb.append(portalURL);
938                            sb.append(themeDisplay.getPathMain());
939                            sb.append("/portal/layout?");
940    
941                            addPortalAuthToken(sb, key);
942    
943                            sb.append("p_l_id");
944                            sb.append(StringPool.EQUAL);
945                            sb.append(processValue(key, _plid));
946                            sb.append(StringPool.AMPERSAND);
947                    }
948                    else {
949                            if (themeDisplay.isFacebook()) {
950                                    sb.append(portalURL);
951                            }
952                            else {
953    
954                                    // A virtual host URL will contain the complete path. Do not
955                                    // append the portal URL if the virtual host URL starts with
956                                    // "http://" or "https://".
957    
958                                    if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
959                                            !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
960    
961                                            sb.append(portalURL);
962                                    }
963    
964                                    sb.append(_layoutFriendlyURL);
965                            }
966    
967                            String friendlyURLPath = getPortletFriendlyURLPath();
968    
969                            if (Validator.isNotNull(friendlyURLPath)) {
970                                    if (themeDisplay.isFacebook()) {
971                                            int pos = friendlyURLPath.indexOf(CharPool.SLASH, 1);
972    
973                                            if (pos != -1) {
974                                                    sb.append(friendlyURLPath.substring(pos));
975                                            }
976                                            else {
977                                                    sb.append(friendlyURLPath);
978                                            }
979                                    }
980                                    else {
981                                            sb.append("/-");
982                                            sb.append(friendlyURLPath);
983                                    }
984                            }
985    
986                            sb.append(StringPool.QUESTION);
987    
988                            addPortalAuthToken(sb, key);
989                    }
990    
991                    addPortletAuthToken(sb, key);
992    
993                    for (Map.Entry<String, String> entry :
994                                    getReservedParameterMap().entrySet()) {
995    
996                            String name = entry.getKey();
997    
998                            if (!isParameterIncludedInPath(name)) {
999                                    sb.append(HttpUtil.encodeURL(name));
1000                                    sb.append(StringPool.EQUAL);
1001                                    sb.append(processValue(key, entry.getValue()));
1002                                    sb.append(StringPool.AMPERSAND);
1003                            }
1004                    }
1005    
1006                    if (_doAsUserId > 0) {
1007                            try {
1008                                    Company company = PortalUtil.getCompany(_request);
1009    
1010                                    sb.append("doAsUserId");
1011                                    sb.append(StringPool.EQUAL);
1012                                    sb.append(processValue(company.getKeyObj(), _doAsUserId));
1013                                    sb.append(StringPool.AMPERSAND);
1014                            }
1015                            catch (Exception e) {
1016                                    _log.error(e);
1017                            }
1018                    }
1019                    else {
1020                            String doAsUserId = themeDisplay.getDoAsUserId();
1021    
1022                            if (Validator.isNotNull(doAsUserId)) {
1023                                    sb.append("doAsUserId");
1024                                    sb.append(StringPool.EQUAL);
1025                                    sb.append(processValue(key, doAsUserId));
1026                                    sb.append(StringPool.AMPERSAND);
1027                            }
1028                    }
1029    
1030                    String doAsUserLanguageId = _doAsUserLanguageId;
1031    
1032                    if (Validator.isNull(doAsUserLanguageId)) {
1033                            doAsUserLanguageId = themeDisplay.getDoAsUserLanguageId();
1034                    }
1035    
1036                    if (Validator.isNotNull(doAsUserLanguageId)) {
1037                            sb.append("doAsUserLanguageId");
1038                            sb.append(StringPool.EQUAL);
1039                            sb.append(processValue(key, doAsUserLanguageId));
1040                            sb.append(StringPool.AMPERSAND);
1041                    }
1042    
1043                    long doAsGroupId = _doAsGroupId;
1044    
1045                    if (doAsGroupId <= 0) {
1046                            doAsGroupId = themeDisplay.getDoAsGroupId();
1047                    }
1048    
1049                    if (doAsGroupId > 0) {
1050                            sb.append("doAsGroupId");
1051                            sb.append(StringPool.EQUAL);
1052                            sb.append(processValue(key, doAsGroupId));
1053                            sb.append(StringPool.AMPERSAND);
1054                    }
1055    
1056                    long refererGroupId = _refererGroupId;
1057    
1058                    if (refererGroupId <= 0) {
1059                            refererGroupId = themeDisplay.getRefererGroupId();
1060                    }
1061    
1062                    if (refererGroupId > 0) {
1063                            sb.append("refererGroupId");
1064                            sb.append(StringPool.EQUAL);
1065                            sb.append(processValue(key, refererGroupId));
1066                            sb.append(StringPool.AMPERSAND);
1067                    }
1068    
1069                    long refererPlid = _refererPlid;
1070    
1071                    if (refererPlid <= 0) {
1072                            refererPlid = themeDisplay.getRefererPlid();
1073                    }
1074    
1075                    if (refererPlid > 0) {
1076                            sb.append("refererPlid");
1077                            sb.append(StringPool.EQUAL);
1078                            sb.append(processValue(key, refererPlid));
1079                            sb.append(StringPool.AMPERSAND);
1080                    }
1081    
1082                    for (Map.Entry<String, String[]> entry :
1083                                    _removePublicRenderParameters.entrySet()) {
1084    
1085                            String lastString = sb.stringAt(sb.index() - 1);
1086    
1087                            if (lastString.charAt(lastString.length() - 1) !=
1088                                            CharPool.AMPERSAND) {
1089    
1090                                    sb.append(StringPool.AMPERSAND);
1091                            }
1092    
1093                            sb.append(HttpUtil.encodeURL(entry.getKey()));
1094                            sb.append(StringPool.EQUAL);
1095                            sb.append(processValue(key, entry.getValue()[0]));
1096                            sb.append(StringPool.AMPERSAND);
1097                    }
1098    
1099                    if (_copyCurrentRenderParameters) {
1100                            mergeRenderParameters();
1101                    }
1102    
1103                    int previousSbIndex = sb.index();
1104    
1105                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1106                            String name = entry.getKey();
1107                            String[] values = entry.getValue();
1108    
1109                            if (isParameterIncludedInPath(name)) {
1110                                    continue;
1111                            }
1112    
1113                            String publicRenderParameterName = getPublicRenderParameterName(
1114                                    name);
1115    
1116                            if (Validator.isNotNull(publicRenderParameterName)) {
1117                                    name = publicRenderParameterName;
1118                            }
1119    
1120                            name = HttpUtil.encodeURL(prependNamespace(name));
1121    
1122                            for (String value : values) {
1123                                    sb.append(name);
1124                                    sb.append(StringPool.EQUAL);
1125                                    sb.append(processValue(key, value));
1126                                    sb.append(StringPool.AMPERSAND);
1127                            }
1128                    }
1129    
1130                    if (sb.index() > previousSbIndex) {
1131                            sb.setIndex(sb.index() - 1);
1132                    }
1133    
1134                    if (_encrypt) {
1135                            sb.append(StringPool.AMPERSAND);
1136                            sb.append(WebKeys.ENCRYPT);
1137                            sb.append("=1");
1138                    }
1139    
1140                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1141                            if (_anchor && (_windowStateString != null) &&
1142                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1143                                    !_windowStateString.equals(
1144                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1145                                    !_windowStateString.equals(
1146                                            LiferayWindowState.POP_UP.toString())) {
1147    
1148                                    String lastString = sb.stringAt(sb.index() - 1);
1149    
1150                                    if (lastString.charAt(lastString.length() - 1) !=
1151                                                    CharPool.AMPERSAND) {
1152    
1153                                            sb.append(StringPool.AMPERSAND);
1154                                    }
1155    
1156                                    sb.append("#p_");
1157                                    sb.append(HttpUtil.encodeURL(_portletId));
1158                            }
1159                    }
1160    
1161                    String result = sb.toString();
1162    
1163                    if (result.endsWith(StringPool.AMPERSAND) ||
1164                            result.endsWith(StringPool.QUESTION)) {
1165    
1166                            result = result.substring(0, result.length() - 1);
1167                    }
1168    
1169                    if (themeDisplay.isFacebook()) {
1170    
1171                            // Facebook requires the path portion of the URL to end with a slash
1172    
1173                            int pos = result.indexOf(CharPool.QUESTION);
1174    
1175                            if (pos == -1) {
1176                                    if (!result.endsWith(StringPool.SLASH)) {
1177                                            result += StringPool.SLASH;
1178                                    }
1179                            }
1180                            else {
1181                                    String path = result.substring(0, pos);
1182    
1183                                    if (!result.endsWith(StringPool.SLASH)) {
1184                                            result = path + StringPool.SLASH + result.substring(pos);
1185                                    }
1186                            }
1187                    }
1188                    else if (!CookieKeys.hasSessionId(_request)) {
1189                            result = PortalUtil.getURLWithSessionId(
1190                                    result, _request.getSession().getId());
1191                    }
1192    
1193                    if (_escapeXml) {
1194                            result = HtmlUtil.escape(result);
1195                    }
1196    
1197                    if (result.length() > Http.URL_MAXIMUM_LENGTH) {
1198                            result = HttpUtil.shortenURL(result, 2);
1199                    }
1200    
1201                    return result;
1202            }
1203    
1204            protected String generateWSRPToString() {
1205                    StringBundler sb = new StringBundler("wsrp_rewrite?");
1206    
1207                    sb.append("wsrp-urlType");
1208                    sb.append(StringPool.EQUAL);
1209    
1210                    if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
1211                            sb.append(HttpUtil.encodeURL("blockingAction"));
1212                    }
1213                    else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
1214                            sb.append(HttpUtil.encodeURL("render"));
1215                    }
1216                    else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1217                            sb.append(HttpUtil.encodeURL("resource"));
1218                    }
1219    
1220                    sb.append(StringPool.AMPERSAND);
1221    
1222                    if (_windowStateString != null) {
1223                            sb.append("wsrp-windowState");
1224                            sb.append(StringPool.EQUAL);
1225                            sb.append(HttpUtil.encodeURL("wsrp:" + _windowStateString));
1226                            sb.append(StringPool.AMPERSAND);
1227                    }
1228    
1229                    if (_portletModeString != null) {
1230                            sb.append("wsrp-mode");
1231                            sb.append(StringPool.EQUAL);
1232                            sb.append(HttpUtil.encodeURL("wsrp:" + _portletModeString));
1233                            sb.append(StringPool.AMPERSAND);
1234                    }
1235    
1236                    if (_resourceID != null) {
1237                            sb.append("wsrp-resourceID");
1238                            sb.append(StringPool.EQUAL);
1239                            sb.append(HttpUtil.encodeURL(_resourceID));
1240                            sb.append(StringPool.AMPERSAND);
1241                    }
1242    
1243                    if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1244                            sb.append("wsrp-resourceCacheability");
1245                            sb.append(StringPool.EQUAL);
1246                            sb.append(HttpUtil.encodeURL(_cacheability));
1247                            sb.append(StringPool.AMPERSAND);
1248                    }
1249    
1250                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1251                            if (_anchor && (_windowStateString != null) &&
1252                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1253                                    !_windowStateString.equals(
1254                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1255                                    !_windowStateString.equals(
1256                                            LiferayWindowState.POP_UP.toString())) {
1257    
1258                                    sb.append("wsrp-fragmentID");
1259                                    sb.append(StringPool.EQUAL);
1260                                    sb.append("#p_");
1261                                    sb.append(HttpUtil.encodeURL(_portletId));
1262                                    sb.append(StringPool.AMPERSAND);
1263                            }
1264                    }
1265    
1266                    if (_copyCurrentRenderParameters) {
1267                            mergeRenderParameters();
1268                    }
1269    
1270                    StringBundler parameterSb = new StringBundler();
1271    
1272                    int previousSbIndex = sb.index();
1273    
1274                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1275                            String name = entry.getKey();
1276                            String[] values = entry.getValue();
1277    
1278                            if (isParameterIncludedInPath(name)) {
1279                                    continue;
1280                            }
1281    
1282                            String publicRenderParameterName = getPublicRenderParameterName(
1283                                    name);
1284    
1285                            if (Validator.isNotNull(publicRenderParameterName)) {
1286                                    name = publicRenderParameterName;
1287                            }
1288    
1289                            name = HttpUtil.encodeURL(prependNamespace(name));
1290    
1291                            for (String value : values) {
1292                                    parameterSb.append(name);
1293                                    parameterSb.append(StringPool.EQUAL);
1294                                    parameterSb.append(HttpUtil.encodeURL(value));
1295                                    parameterSb.append(StringPool.AMPERSAND);
1296                            }
1297                    }
1298    
1299                    if (sb.index() > previousSbIndex) {
1300                            sb.setIndex(sb.index() - 1);
1301                    }
1302    
1303                    sb.append("wsrp-navigationalState");
1304                    sb.append(StringPool.EQUAL);
1305    
1306                    byte[] parameterBytes = null;
1307    
1308                    try {
1309                            String parameterString = parameterSb.toString();
1310    
1311                            parameterBytes = parameterString.getBytes(StringPool.UTF8);
1312                    }
1313                    catch (UnsupportedEncodingException uee) {
1314                            if (_log.isWarnEnabled()) {
1315                                    _log.warn(uee, uee);
1316                            }
1317                    }
1318    
1319                    String navigationalState = Base64.toURLSafe(
1320                            Base64.encode(parameterBytes));
1321    
1322                    sb.append(navigationalState);
1323    
1324                    sb.append("/wsrp_rewrite");
1325    
1326                    return sb.toString();
1327            }
1328    
1329            protected String getPublicRenderParameterName(String name) {
1330                    Portlet portlet = getPortlet();
1331    
1332                    String publicRenderParameterName = null;
1333    
1334                    if (portlet != null) {
1335                            PublicRenderParameter publicRenderParameter =
1336                                    portlet.getPublicRenderParameter(name);
1337    
1338                            if (publicRenderParameter != null) {
1339                                    QName qName = publicRenderParameter.getQName();
1340    
1341                                    publicRenderParameterName =
1342                                            PortletQNameUtil.getPublicRenderParameterName(qName);
1343                            }
1344                    }
1345    
1346                    return publicRenderParameterName;
1347            }
1348    
1349            protected boolean isBlankValue(String[] value) {
1350                    if ((value != null) && (value.length == 1) &&
1351                            value[0].equals(StringPool.BLANK)) {
1352    
1353                            return true;
1354                    }
1355                    else {
1356                            return false;
1357                    }
1358            }
1359    
1360            protected void mergeRenderParameters() {
1361                    String namespace = getNamespace();
1362    
1363                    Layout layout = getLayout();
1364    
1365                    Map<String, String[]> renderParameters = RenderParametersPool.get(
1366                            _request, layout.getPlid(), getPortlet().getPortletId());
1367    
1368                    for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
1369                            String name = entry.getKey();
1370    
1371                            if (name.contains(namespace)) {
1372                                    name = name.substring(namespace.length());
1373                            }
1374    
1375                            if (!_lifecycle.equals(PortletRequest.RESOURCE_PHASE) &&
1376                                    (_removedParameterNames != null) &&
1377                                    _removedParameterNames.contains(name)) {
1378    
1379                                    continue;
1380                            }
1381    
1382                            String[] oldValues = entry.getValue();
1383                            String[] newValues = _params.get(name);
1384    
1385                            if (newValues == null) {
1386                                    _params.put(name, oldValues);
1387                            }
1388                            else if (isBlankValue(newValues)) {
1389                                    _params.remove(name);
1390                            }
1391                            else {
1392                                    newValues = ArrayUtil.append(newValues, oldValues);
1393    
1394                                    _params.put(name, newValues);
1395                            }
1396                    }
1397            }
1398    
1399            protected String prependNamespace(String name) {
1400                    String namespace = getNamespace();
1401    
1402                    if (!PortalUtil.isReservedParameter(name) &&
1403                            !name.startsWith(PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE) &&
1404                            !name.startsWith(namespace)) {
1405    
1406                            return namespace.concat(name);
1407                    }
1408                    else {
1409                            return name;
1410                    }
1411            }
1412    
1413            protected String processValue(Key key, int value) {
1414                    return processValue(key, String.valueOf(value));
1415            }
1416    
1417            protected String processValue(Key key, long value) {
1418                    return processValue(key, String.valueOf(value));
1419            }
1420    
1421            protected String processValue(Key key, String value) {
1422                    if (key == null) {
1423                            return HttpUtil.encodeURL(value);
1424                    }
1425    
1426                    try {
1427                            return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1428                    }
1429                    catch (EncryptorException ee) {
1430                            return value;
1431                    }
1432            }
1433    
1434            protected void removeParameter(String name) {
1435                    if (_params.containsKey(name)) {
1436                            _params.remove(name);
1437                    }
1438            }
1439    
1440            private static final Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1441    
1442            private boolean _anchor = true;
1443            private String _cacheability = ResourceURL.PAGE;
1444            private boolean _copyCurrentRenderParameters;
1445            private long _doAsGroupId;
1446            private long _doAsUserId;
1447            private String _doAsUserLanguageId;
1448            private boolean _encrypt;
1449            private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1450            private Layout _layout;
1451            private String _layoutFriendlyURL;
1452            private String _lifecycle;
1453            private String _namespace;
1454            private final Set<String> _parametersIncludedInPath;
1455            private Map<String, String[]> _params;
1456            private long _plid;
1457            private Portlet _portlet;
1458            private String _portletId;
1459            private String _portletModeString;
1460            private final PortletRequest _portletRequest;
1461            private long _refererGroupId;
1462            private long _refererPlid;
1463            private Set<String> _removedParameterNames;
1464            private final Map<String, String[]> _removePublicRenderParameters;
1465            private final HttpServletRequest _request;
1466            private Map<String, String> _reservedParameters;
1467            private String _resourceID;
1468            private boolean _secure;
1469            private String _toString;
1470            private boolean _windowStateRestoreCurrentView;
1471            private String _windowStateString;
1472            private final boolean _wsrp;
1473    
1474            private class ToStringPrivilegedAction implements PrivilegedAction<String> {
1475    
1476                    @Override
1477                    public String run() {
1478                            if (_wsrp) {
1479                                    return generateWSRPToString();
1480                            }
1481    
1482                            return generateToString();
1483                    }
1484    
1485            }
1486    
1487    }