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