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