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