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