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