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                    String portalURL = null;
849    
850                    if (themeDisplay.isFacebook()) {
851                            portalURL =
852                                    FacebookUtil.FACEBOOK_APPS_URL +
853                                            themeDisplay.getFacebookCanvasPageURL();
854                    }
855                    else {
856                            portalURL = PortalUtil.getPortalURL(_request, _secure);
857                    }
858    
859                    try {
860                            if (_layoutFriendlyURL == null) {
861                                    Layout layout = getLayout();
862    
863                                    if (layout != null) {
864                                            _layoutFriendlyURL = GetterUtil.getString(
865                                                    PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
866    
867                                            if (_secure) {
868                                                    _layoutFriendlyURL = HttpUtil.protocolize(
869                                                            _layoutFriendlyURL,
870                                                            PropsValues.WEB_SERVER_HTTPS_PORT, true);
871                                            }
872                                    }
873                            }
874                    }
875                    catch (Exception e) {
876                            _log.error(e);
877                    }
878    
879                    Key key = null;
880    
881                    try {
882                            if (_encrypt) {
883                                    Company company = PortalUtil.getCompany(_request);
884    
885                                    key = company.getKeyObj();
886                            }
887                    }
888                    catch (Exception e) {
889                            _log.error(e);
890                    }
891    
892                    if (Validator.isNull(_layoutFriendlyURL)) {
893                            sb.append(portalURL);
894                            sb.append(themeDisplay.getPathMain());
895                            sb.append("/portal/layout?");
896    
897                            addPortalAuthToken(sb, key);
898    
899                            sb.append("p_l_id");
900                            sb.append(StringPool.EQUAL);
901                            sb.append(processValue(key, _plid));
902                            sb.append(StringPool.AMPERSAND);
903                    }
904                    else {
905                            if (themeDisplay.isFacebook()) {
906                                    sb.append(portalURL);
907                            }
908                            else {
909    
910                                    // A virtual host URL will contain the complete path. Do not
911                                    // append the portal URL if the virtual host URL starts with
912                                    // "http://" or "https://".
913    
914                                    if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
915                                            !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
916    
917                                            sb.append(portalURL);
918                                    }
919    
920                                    sb.append(_layoutFriendlyURL);
921                            }
922    
923                            String friendlyURLPath = getPortletFriendlyURLPath();
924    
925                            if (Validator.isNotNull(friendlyURLPath)) {
926                                    if (themeDisplay.isFacebook()) {
927                                            int pos = friendlyURLPath.indexOf(CharPool.SLASH, 1);
928    
929                                            if (pos != -1) {
930                                                    sb.append(friendlyURLPath.substring(pos));
931                                            }
932                                            else {
933                                                    sb.append(friendlyURLPath);
934                                            }
935                                    }
936                                    else {
937                                            sb.append("/-");
938                                            sb.append(friendlyURLPath);
939                                    }
940                            }
941    
942                            sb.append(StringPool.QUESTION);
943    
944                            addPortalAuthToken(sb, key);
945                    }
946    
947                    addPortletAuthToken(sb, key);
948    
949                    for (Map.Entry<String, String> entry :
950                                    getReservedParameterMap().entrySet()) {
951    
952                            String name = entry.getKey();
953    
954                            if (!isParameterIncludedInPath(name)) {
955                                    sb.append(HttpUtil.encodeURL(name));
956                                    sb.append(StringPool.EQUAL);
957                                    sb.append(processValue(key, entry.getValue()));
958                                    sb.append(StringPool.AMPERSAND);
959                            }
960                    }
961    
962                    if (_doAsUserId > 0) {
963                            try {
964                                    Company company = PortalUtil.getCompany(_request);
965    
966                                    sb.append("doAsUserId");
967                                    sb.append(StringPool.EQUAL);
968                                    sb.append(processValue(company.getKeyObj(), _doAsUserId));
969                                    sb.append(StringPool.AMPERSAND);
970                            }
971                            catch (Exception e) {
972                                    _log.error(e);
973                            }
974                    }
975                    else {
976                            String doAsUserId = themeDisplay.getDoAsUserId();
977    
978                            if (Validator.isNotNull(doAsUserId)) {
979                                    sb.append("doAsUserId");
980                                    sb.append(StringPool.EQUAL);
981                                    sb.append(processValue(key, doAsUserId));
982                                    sb.append(StringPool.AMPERSAND);
983                            }
984                    }
985    
986                    String doAsUserLanguageId = _doAsUserLanguageId;
987    
988                    if (Validator.isNull(doAsUserLanguageId)) {
989                            doAsUserLanguageId = themeDisplay.getDoAsUserLanguageId();
990                    }
991    
992                    if (Validator.isNotNull(doAsUserLanguageId)) {
993                            sb.append("doAsUserLanguageId");
994                            sb.append(StringPool.EQUAL);
995                            sb.append(processValue(key, doAsUserLanguageId));
996                            sb.append(StringPool.AMPERSAND);
997                    }
998    
999                    long doAsGroupId = _doAsGroupId;
1000    
1001                    if (doAsGroupId <= 0) {
1002                            doAsGroupId = themeDisplay.getDoAsGroupId();
1003                    }
1004    
1005                    if (doAsGroupId > 0) {
1006                            sb.append("doAsGroupId");
1007                            sb.append(StringPool.EQUAL);
1008                            sb.append(processValue(key, doAsGroupId));
1009                            sb.append(StringPool.AMPERSAND);
1010                    }
1011    
1012                    long refererGroupId = _refererGroupId;
1013    
1014                    if (refererGroupId <= 0) {
1015                            refererGroupId = themeDisplay.getRefererGroupId();
1016                    }
1017    
1018                    if (refererGroupId > 0) {
1019                            sb.append("refererGroupId");
1020                            sb.append(StringPool.EQUAL);
1021                            sb.append(processValue(key, refererGroupId));
1022                            sb.append(StringPool.AMPERSAND);
1023                    }
1024    
1025                    long refererPlid = _refererPlid;
1026    
1027                    if (refererPlid <= 0) {
1028                            refererPlid = themeDisplay.getRefererPlid();
1029                    }
1030    
1031                    if (refererPlid > 0) {
1032                            sb.append("refererPlid");
1033                            sb.append(StringPool.EQUAL);
1034                            sb.append(processValue(key, refererPlid));
1035                            sb.append(StringPool.AMPERSAND);
1036                    }
1037    
1038                    String controlPanelCategory = _controlPanelCategory;
1039    
1040                    if (Validator.isNull(controlPanelCategory)) {
1041                            HttpServletRequest request = PortalUtil.getOriginalServletRequest(
1042                                    _request);
1043    
1044                            controlPanelCategory = ParamUtil.getString(
1045                                    request, "controlPanelCategory");
1046                    }
1047    
1048                    if (Validator.isNotNull(controlPanelCategory)) {
1049                            sb.append("controlPanelCategory");
1050                            sb.append(StringPool.EQUAL);
1051                            sb.append(processValue(key, controlPanelCategory));
1052                            sb.append(StringPool.AMPERSAND);
1053                    }
1054    
1055                    for (Map.Entry<String, String[]> entry :
1056                                    _removePublicRenderParameters.entrySet()) {
1057    
1058                            String lastString = sb.stringAt(sb.index() - 1);
1059    
1060                            if (lastString.charAt(lastString.length() - 1) !=
1061                                            CharPool.AMPERSAND) {
1062    
1063                                    sb.append(StringPool.AMPERSAND);
1064                            }
1065    
1066                            sb.append(HttpUtil.encodeURL(entry.getKey()));
1067                            sb.append(StringPool.EQUAL);
1068                            sb.append(processValue(key, entry.getValue()[0]));
1069                            sb.append(StringPool.AMPERSAND);
1070                    }
1071    
1072                    if (_copyCurrentRenderParameters) {
1073                            mergeRenderParameters();
1074                    }
1075    
1076                    int previousSbIndex = sb.index();
1077    
1078                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1079                            String name = entry.getKey();
1080                            String[] values = entry.getValue();
1081    
1082                            if (isParameterIncludedInPath(name)) {
1083                                    continue;
1084                            }
1085    
1086                            String publicRenderParameterName = getPublicRenderParameterName(
1087                                    name);
1088    
1089                            if (Validator.isNotNull(publicRenderParameterName)) {
1090                                    name = publicRenderParameterName;
1091                            }
1092    
1093                            name = HttpUtil.encodeURL(prependNamespace(name));
1094    
1095                            for (String value : values) {
1096                                    sb.append(name);
1097                                    sb.append(StringPool.EQUAL);
1098                                    sb.append(processValue(key, value));
1099                                    sb.append(StringPool.AMPERSAND);
1100                            }
1101                    }
1102    
1103                    if (sb.index() > previousSbIndex) {
1104                            sb.setIndex(sb.index() - 1);
1105                    }
1106    
1107                    if (_encrypt) {
1108                            sb.append(StringPool.AMPERSAND);
1109                            sb.append(WebKeys.ENCRYPT);
1110                            sb.append("=1");
1111                    }
1112    
1113                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1114                            if (_anchor && (_windowStateString != null) &&
1115                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1116                                    !_windowStateString.equals(
1117                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1118                                    !_windowStateString.equals(
1119                                            LiferayWindowState.POP_UP.toString())) {
1120    
1121                                    String lastString = sb.stringAt(sb.index() - 1);
1122    
1123                                    if (lastString.charAt(lastString.length() - 1) !=
1124                                                    CharPool.AMPERSAND) {
1125    
1126                                            sb.append(StringPool.AMPERSAND);
1127                                    }
1128    
1129                                    sb.append("#p_");
1130                                    sb.append(HttpUtil.encodeURL(_portletId));
1131                            }
1132                    }
1133    
1134                    String result = sb.toString();
1135    
1136                    if (result.endsWith(StringPool.AMPERSAND) ||
1137                            result.endsWith(StringPool.QUESTION)) {
1138    
1139                            result = result.substring(0, result.length() - 1);
1140                    }
1141    
1142                    if (themeDisplay.isFacebook()) {
1143    
1144                            // Facebook requires the path portion of the URL to end with a slash
1145    
1146                            int pos = result.indexOf(CharPool.QUESTION);
1147    
1148                            if (pos == -1) {
1149                                    if (!result.endsWith(StringPool.SLASH)) {
1150                                            result += StringPool.SLASH;
1151                                    }
1152                            }
1153                            else {
1154                                    String path = result.substring(0, pos);
1155    
1156                                    if (!result.endsWith(StringPool.SLASH)) {
1157                                            result = path + StringPool.SLASH + result.substring(pos);
1158                                    }
1159                            }
1160                    }
1161                    else if (!CookieKeys.hasSessionId(_request)) {
1162                            result = PortalUtil.getURLWithSessionId(
1163                                    result, _request.getSession().getId());
1164                    }
1165    
1166                    if (_escapeXml) {
1167                            result = HtmlUtil.escape(result);
1168                    }
1169    
1170                    if (result.length() > Http.URL_MAXIMUM_LENGTH) {
1171                            result = HttpUtil.shortenURL(result, 2);
1172                    }
1173    
1174                    return result;
1175            }
1176    
1177            protected String generateWSRPToString() {
1178                    StringBundler sb = new StringBundler("wsrp_rewrite?");
1179    
1180                    sb.append("wsrp-urlType");
1181                    sb.append(StringPool.EQUAL);
1182    
1183                    if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
1184                            sb.append(HttpUtil.encodeURL("blockingAction"));
1185                    }
1186                    else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
1187                            sb.append(HttpUtil.encodeURL("render"));
1188                    }
1189                    else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1190                            sb.append(HttpUtil.encodeURL("resource"));
1191                    }
1192    
1193                    sb.append(StringPool.AMPERSAND);
1194    
1195                    if (_windowStateString != null) {
1196                            sb.append("wsrp-windowState");
1197                            sb.append(StringPool.EQUAL);
1198                            sb.append(HttpUtil.encodeURL("wsrp:" + _windowStateString));
1199                            sb.append(StringPool.AMPERSAND);
1200                    }
1201    
1202                    if (_portletModeString != null) {
1203                            sb.append("wsrp-mode");
1204                            sb.append(StringPool.EQUAL);
1205                            sb.append(HttpUtil.encodeURL("wsrp:" + _portletModeString));
1206                            sb.append(StringPool.AMPERSAND);
1207                    }
1208    
1209                    if (_resourceID != null) {
1210                            sb.append("wsrp-resourceID");
1211                            sb.append(StringPool.EQUAL);
1212                            sb.append(HttpUtil.encodeURL(_resourceID));
1213                            sb.append(StringPool.AMPERSAND);
1214                    }
1215    
1216                    if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1217                            sb.append("wsrp-resourceCacheability");
1218                            sb.append(StringPool.EQUAL);
1219                            sb.append(HttpUtil.encodeURL(_cacheability));
1220                            sb.append(StringPool.AMPERSAND);
1221                    }
1222    
1223                    if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1224                            if (_anchor && (_windowStateString != null) &&
1225                                    !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1226                                    !_windowStateString.equals(
1227                                            LiferayWindowState.EXCLUSIVE.toString()) &&
1228                                    !_windowStateString.equals(
1229                                            LiferayWindowState.POP_UP.toString())) {
1230    
1231                                    sb.append("wsrp-fragmentID");
1232                                    sb.append(StringPool.EQUAL);
1233                                    sb.append("#p_");
1234                                    sb.append(HttpUtil.encodeURL(_portletId));
1235                                    sb.append(StringPool.AMPERSAND);
1236                            }
1237                    }
1238    
1239                    if (_copyCurrentRenderParameters) {
1240                            mergeRenderParameters();
1241                    }
1242    
1243                    StringBundler parameterSb = new StringBundler();
1244    
1245                    int previousSbIndex = sb.index();
1246    
1247                    for (Map.Entry<String, String[]> entry : _params.entrySet()) {
1248                            String name = entry.getKey();
1249                            String[] values = entry.getValue();
1250    
1251                            if (isParameterIncludedInPath(name)) {
1252                                    continue;
1253                            }
1254    
1255                            String publicRenderParameterName = getPublicRenderParameterName(
1256                                    name);
1257    
1258                            if (Validator.isNotNull(publicRenderParameterName)) {
1259                                    name = publicRenderParameterName;
1260                            }
1261    
1262                            name = HttpUtil.encodeURL(prependNamespace(name));
1263    
1264                            for (String value : values) {
1265                                    parameterSb.append(name);
1266                                    parameterSb.append(StringPool.EQUAL);
1267                                    parameterSb.append(HttpUtil.encodeURL(value));
1268                                    parameterSb.append(StringPool.AMPERSAND);
1269                            }
1270                    }
1271    
1272                    if (sb.index() > previousSbIndex) {
1273                            sb.setIndex(sb.index() - 1);
1274                    }
1275    
1276                    sb.append("wsrp-navigationalState");
1277                    sb.append(StringPool.EQUAL);
1278    
1279                    byte[] parameterBytes = null;
1280    
1281                    try {
1282                            String parameterString = parameterSb.toString();
1283    
1284                            parameterBytes = parameterString.getBytes(StringPool.UTF8);
1285                    }
1286                    catch (UnsupportedEncodingException uee) {
1287                            if (_log.isWarnEnabled()) {
1288                                    _log.warn(uee, uee);
1289                            }
1290                    }
1291    
1292                    String navigationalState = Base64.toURLSafe(
1293                            Base64.encode(parameterBytes));
1294    
1295                    sb.append(navigationalState);
1296    
1297                    sb.append("/wsrp_rewrite");
1298    
1299                    return sb.toString();
1300            }
1301    
1302            protected String getPublicRenderParameterName(String name) {
1303                    Portlet portlet = getPortlet();
1304    
1305                    String publicRenderParameterName = null;
1306    
1307                    if (portlet != null) {
1308                            PublicRenderParameter publicRenderParameter =
1309                                    portlet.getPublicRenderParameter(name);
1310    
1311                            if (publicRenderParameter != null) {
1312                                    QName qName = publicRenderParameter.getQName();
1313    
1314                                    publicRenderParameterName =
1315                                            PortletQNameUtil.getPublicRenderParameterName(qName);
1316                            }
1317                    }
1318    
1319                    return publicRenderParameterName;
1320            }
1321    
1322            protected boolean isBlankValue(String[] value) {
1323                    if ((value != null) && (value.length == 1) &&
1324                            value[0].equals(StringPool.BLANK)) {
1325    
1326                            return true;
1327                    }
1328                    else {
1329                            return false;
1330                    }
1331            }
1332    
1333            protected void mergeRenderParameters() {
1334                    String namespace = getNamespace();
1335    
1336                    Layout layout = getLayout();
1337    
1338                    Map<String, String[]> renderParameters = RenderParametersPool.get(
1339                            _request, layout.getPlid(), getPortlet().getPortletId());
1340    
1341                    for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
1342                            String name = entry.getKey();
1343    
1344                            if (name.contains(namespace)) {
1345                                    name = name.substring(namespace.length());
1346                            }
1347    
1348                            if (!_lifecycle.equals(PortletRequest.RESOURCE_PHASE) &&
1349                                    (_removedParameterNames != null) &&
1350                                    _removedParameterNames.contains(name)) {
1351    
1352                                    continue;
1353                            }
1354    
1355                            String[] oldValues = entry.getValue();
1356                            String[] newValues = _params.get(name);
1357    
1358                            if (newValues == null) {
1359                                    _params.put(name, oldValues);
1360                            }
1361                            else if (isBlankValue(newValues)) {
1362                                    _params.remove(name);
1363                            }
1364                            else {
1365                                    newValues = ArrayUtil.append(newValues, oldValues);
1366    
1367                                    _params.put(name, newValues);
1368                            }
1369                    }
1370            }
1371    
1372            protected String prependNamespace(String name) {
1373                    String namespace = getNamespace();
1374    
1375                    if (!PortalUtil.isReservedParameter(name) &&
1376                            !name.startsWith(PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE) &&
1377                            !name.startsWith(namespace)) {
1378    
1379                            return namespace.concat(name);
1380                    }
1381                    else {
1382                            return name;
1383                    }
1384            }
1385    
1386            protected String processValue(Key key, int value) {
1387                    return processValue(key, String.valueOf(value));
1388            }
1389    
1390            protected String processValue(Key key, long value) {
1391                    return processValue(key, String.valueOf(value));
1392            }
1393    
1394            protected String processValue(Key key, String value) {
1395                    if (key == null) {
1396                            return HttpUtil.encodeURL(value);
1397                    }
1398    
1399                    try {
1400                            return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1401                    }
1402                    catch (EncryptorException ee) {
1403                            return value;
1404                    }
1405            }
1406    
1407            private static Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1408    
1409            private boolean _anchor = true;
1410            private String _cacheability = ResourceURL.PAGE;
1411            private String _controlPanelCategory;
1412            private boolean _copyCurrentRenderParameters;
1413            private long _doAsGroupId;
1414            private long _doAsUserId;
1415            private String _doAsUserLanguageId;
1416            private boolean _encrypt;
1417            private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1418            private Layout _layout;
1419            private String _layoutFriendlyURL;
1420            private String _lifecycle;
1421            private String _namespace;
1422            private Set<String> _parametersIncludedInPath;
1423            private Map<String, String[]> _params;
1424            private long _plid;
1425            private Portlet _portlet;
1426            private String _portletId;
1427            private String _portletModeString;
1428            private PortletRequest _portletRequest;
1429            private long _refererGroupId;
1430            private long _refererPlid;
1431            private Set<String> _removedParameterNames;
1432            private Map<String, String[]> _removePublicRenderParameters;
1433            private HttpServletRequest _request;
1434            private Map<String, String> _reservedParameters;
1435            private String _resourceID;
1436            private boolean _secure;
1437            private String _toString;
1438            private boolean _windowStateRestoreCurrentView;
1439            private String _windowStateString;
1440            private boolean _wsrp;
1441    
1442            private class ToStringPrivilegedAction implements PrivilegedAction<String> {
1443    
1444                    @Override
1445                    public String run() {
1446                            if (_wsrp) {
1447                                    return generateWSRPToString();
1448                            }
1449    
1450                            return generateToString();
1451                    }
1452            }
1453    
1454    }