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