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