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