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