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