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