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 setPlid(long plid) {
471         _plid = plid;
472 
473         // Clear cache
474 
475         _toString = null;
476     }
477 
478     public void setPortletId(String portletId) {
479         _portletId = portletId;
480 
481         // Clear cache
482 
483         _toString = null;
484     }
485 
486     public void setPortletMode(String portletMode) throws PortletModeException {
487         setPortletMode(PortletModeFactory.getPortletMode(portletMode));
488     }
489 
490     public void setPortletMode(PortletMode portletMode)
491         throws PortletModeException {
492 
493         if (_portletRequest != null) {
494             if (!getPortlet().hasPortletMode(
495                     _portletRequest.getResponseContentType(), portletMode)) {
496 
497                 throw new PortletModeException(
498                     portletMode.toString(), portletMode);
499             }
500         }
501 
502         _portletMode = portletMode;
503 
504         // Clear cache
505 
506         _toString = null;
507     }
508 
509     public void setProperty(String key, String value) {
510         if (key == null) {
511             throw new IllegalArgumentException();
512         }
513     }
514 
515     public void setResourceID(String resourceID) {
516         _resourceID = resourceID;
517     }
518 
519     public void setSecure(boolean secure) {
520         _secure = secure;
521 
522         // Clear cache
523 
524         _toString = null;
525     }
526 
527     public void setWindowState(String windowState) throws WindowStateException {
528         setWindowState(WindowStateFactory.getWindowState(windowState));
529     }
530 
531     public void setWindowState(WindowState windowState)
532         throws WindowStateException {
533 
534         if (_portletRequest != null) {
535             if (!_portletRequest.isWindowStateAllowed(windowState)) {
536                 throw new WindowStateException(
537                     windowState.toString(), windowState);
538             }
539         }
540 
541         if (LiferayWindowState.isWindowStatePreserved(
542                 getWindowState(), windowState)) {
543 
544             _windowState = windowState;
545         }
546 
547         // Clear cache
548 
549         _toString = null;
550     }
551 
552     public void setURLType(ChannelURLType urlType) {
553         _urlType = urlType;
554 
555         // Clear cache
556 
557         _toString = null;
558     }
559 
560     public String toString() {
561         if (_toString != null) {
562             return _toString;
563         }
564 
565         _toString = generateToString();
566 
567         return _toString;
568     }
569 
570     public void write(Writer writer) throws IOException {
571         write(writer, _escapeXml);
572     }
573 
574     public void write(Writer writer, boolean escapeXml) throws IOException {
575         String toString = toString();
576 
577         if (escapeXml && !_escapeXml) {
578             toString = URLHelper.escapeURL(toString);
579         }
580 
581         writer.write(toString());
582     }
583 
584     protected String generateToString() {
585         StringBuilder sb = new StringBuilder();
586 
587         ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
588             WebKeys.THEME_DISPLAY);
589 
590         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
591 
592         Portlet portlet = getPortlet();
593 
594         String portalURL = null;
595 
596         if (themeDisplay.isFacebook()) {
597             portalURL =
598                 FacebookUtil.FACEBOOK_APPS_URL +
599                     themeDisplay.getFacebookCanvasPageURL();
600         }
601         else {
602             portalURL = PortalUtil.getPortalURL(_request, _secure);
603         }
604 
605         try {
606             if (_layoutFriendlyURL == null) {
607                 Layout layout = getLayout();
608 
609                 if (layout != null) {
610                     _layoutFriendlyURL = GetterUtil.getString(
611                         PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
612                 }
613             }
614         }
615         catch (Exception e) {
616             _log.error(e);
617         }
618 
619         Key key = null;
620 
621         try {
622             if (_encrypt) {
623                 Company company = PortalUtil.getCompany(_request);
624 
625                 key = company.getKeyObj();
626             }
627         }
628         catch (Exception e) {
629             _log.error(e);
630         }
631 
632         if (Validator.isNull(_layoutFriendlyURL)) {
633             sb.append(portalURL);
634             sb.append(themeDisplay.getPathMain());
635             sb.append("/portal/layout?");
636 
637             sb.append("p_l_id");
638             sb.append(StringPool.EQUAL);
639             sb.append(processValue(key, _plid));
640             sb.append(StringPool.AMPERSAND);
641         }
642         else {
643 
644             // A virtual host URL will contain the complete path. Do not append
645             // the portal URL if the virtual host URL starts with "http://" or
646             // "https://".
647 
648             if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
649                 !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
650 
651                 sb.append(portalURL);
652             }
653 
654             if (!themeDisplay.isFacebook()) {
655                 sb.append(_layoutFriendlyURL);
656             }
657 
658             String friendlyURLPath = getPortletFriendlyURLPath();
659 
660             if (Validator.isNotNull(friendlyURLPath)) {
661                 if (themeDisplay.isFacebook()) {
662                     int pos = friendlyURLPath.indexOf(StringPool.SLASH, 1);
663 
664                     if (pos != -1) {
665                         sb.append(friendlyURLPath.substring(pos));
666                     }
667                     else {
668                         sb.append(friendlyURLPath);
669                     }
670                 }
671                 else {
672                     sb.append("/-");
673                     sb.append(friendlyURLPath);
674                 }
675 
676                 if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
677                     addParameterIncludedInPath("p_p_lifecycle");
678                 }
679 
680                 //if ((_windowState != null) &&
681                 //  _windowState.equals(WindowState.MAXIMIZED)) {
682 
683                     addParameterIncludedInPath("p_p_state");
684                 //}
685 
686                 //if ((_portletMode != null) &&
687                 //  _portletMode.equals(PortletMode.VIEW)) {
688 
689                     addParameterIncludedInPath("p_p_mode");
690                 //}
691 
692                 addParameterIncludedInPath("p_p_col_id");
693                 addParameterIncludedInPath("p_p_col_pos");
694                 addParameterIncludedInPath("p_p_col_count");
695             }
696 
697             sb.append(StringPool.QUESTION);
698         }
699 
700         if (!isParameterIncludedInPath("p_p_id")) {
701             sb.append("p_p_id");
702             sb.append(StringPool.EQUAL);
703             sb.append(processValue(key, _portletId));
704             sb.append(StringPool.AMPERSAND);
705         }
706 
707         if (!isParameterIncludedInPath("p_p_lifecycle")) {
708             sb.append("p_p_lifecycle");
709             sb.append(StringPool.EQUAL);
710 
711             if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
712                 sb.append(processValue(key, "1"));
713             }
714             else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
715                 sb.append(processValue(key, "0"));
716             }
717             else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
718                 sb.append(processValue(key, "2"));
719             }
720 
721             sb.append(StringPool.AMPERSAND);
722         }
723 
724         if (PropsValues.PORTLET_CONTAINER_IMPL_SUN &&
725             !isParameterIncludedInPath("p_p_url_type")) {
726 
727             sb.append("p_p_url_type");
728             sb.append(StringPool.EQUAL);
729 
730             if (ChannelURLType.ACTION.equals(_urlType)) {
731                 sb.append(processValue(key, "1"));
732             }
733             else if (ChannelURLType.RENDER.equals(_urlType)) {
734                 sb.append(processValue(key, "0"));
735             }
736             else if (ChannelURLType.RESOURCE.equals(_urlType)) {
737                 sb.append(processValue(key, "2"));
738             }
739             else {
740                 sb.append(processValue(key, "0"));
741             }
742 
743             sb.append(StringPool.AMPERSAND);
744         }
745 
746         if (!isParameterIncludedInPath("p_p_state")) {
747             if (_windowState != null) {
748                 sb.append("p_p_state");
749                 sb.append(StringPool.EQUAL);
750                 sb.append(processValue(key, _windowState.toString()));
751                 sb.append(StringPool.AMPERSAND);
752             }
753         }
754 
755         if (!isParameterIncludedInPath("p_p_mode")) {
756             if (_portletMode != null) {
757                 sb.append("p_p_mode");
758                 sb.append(StringPool.EQUAL);
759                 sb.append(processValue(key, _portletMode.toString()));
760                 sb.append(StringPool.AMPERSAND);
761             }
762         }
763 
764         if (!isParameterIncludedInPath("p_p_resource_id")) {
765             if (_resourceID != null) {
766                 sb.append("p_p_resource_id");
767                 sb.append(StringPool.EQUAL);
768                 sb.append(processValue(key, _resourceID));
769                 sb.append(StringPool.AMPERSAND);
770             }
771         }
772 
773         if (!isParameterIncludedInPath("p_p_cacheability")) {
774             if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
775                 sb.append("p_p_cacheability");
776                 sb.append(StringPool.EQUAL);
777                 sb.append(processValue(key, _cacheability));
778                 sb.append(StringPool.AMPERSAND);
779             }
780         }
781 
782         if (!isParameterIncludedInPath("p_p_col_id")) {
783             if (Validator.isNotNull(portletDisplay.getColumnId())) {
784                 sb.append("p_p_col_id");
785                 sb.append(StringPool.EQUAL);
786                 sb.append(processValue(key, portletDisplay.getColumnId()));
787                 sb.append(StringPool.AMPERSAND);
788             }
789         }
790 
791         if (!isParameterIncludedInPath("p_p_col_pos")) {
792             if (portletDisplay.getColumnPos() > 0) {
793                 sb.append("p_p_col_pos");
794                 sb.append(StringPool.EQUAL);
795                 sb.append(processValue(key, portletDisplay.getColumnPos()));
796                 sb.append(StringPool.AMPERSAND);
797             }
798         }
799 
800         if (!isParameterIncludedInPath("p_p_col_count")) {
801             if (portletDisplay.getColumnCount() > 0) {
802                 sb.append("p_p_col_count");
803                 sb.append(StringPool.EQUAL);
804                 sb.append(processValue(key, portletDisplay.getColumnCount()));
805                 sb.append(StringPool.AMPERSAND);
806             }
807         }
808 
809         if (_doAsUserId > 0) {
810             try {
811                 Company company = PortalUtil.getCompany(_request);
812 
813                 sb.append("doAsUserId");
814                 sb.append(StringPool.EQUAL);
815                 sb.append(processValue(company.getKeyObj(), _doAsUserId));
816                 sb.append(StringPool.AMPERSAND);
817             }
818             catch (Exception e) {
819                 _log.error(e);
820             }
821         }
822         else {
823             String doAsUserId = themeDisplay.getDoAsUserId();
824 
825             if (Validator.isNotNull(doAsUserId)) {
826                 sb.append("doAsUserId");
827                 sb.append(StringPool.EQUAL);
828                 sb.append(processValue(key, doAsUserId));
829                 sb.append(StringPool.AMPERSAND);
830             }
831         }
832 
833         if (_copyCurrentRenderParameters) {
834             Enumeration<String> enu = _request.getParameterNames();
835 
836             while (enu.hasMoreElements()) {
837                 String name = enu.nextElement();
838 
839                 String[] oldValues = _request.getParameterValues(name);
840                 String[] newValues = _params.get(name);
841 
842                 if (newValues == null) {
843                     _params.put(name, oldValues);
844                 }
845                 else if (isBlankValue(newValues)) {
846                     _params.remove(name);
847                 }
848                 else {
849                     newValues = ArrayUtil.append(newValues, oldValues);
850 
851                     _params.put(name, newValues);
852                 }
853             }
854         }
855 
856         Iterator<Map.Entry<String, String[]>> itr =
857             _params.entrySet().iterator();
858 
859         while (itr.hasNext()) {
860             Map.Entry<String, String[]> entry = itr.next();
861 
862             String name = entry.getKey();
863             String[] values = entry.getValue();
864 
865             String identifier = null;
866 
867             if (portlet != null) {
868                 PublicRenderParameter publicRenderParameter =
869                     portlet.getPublicRenderParameter(name);
870 
871                 if (publicRenderParameter != null) {
872                     QName qName = publicRenderParameter.getQName();
873 
874                     if (_copyCurrentPublicRenderParameters) {
875                         String[] oldValues = _request.getParameterValues(name);
876 
877                         if (oldValues != null) {
878                             if (values == null) {
879                                 values = oldValues;
880                             }
881                             else {
882                                 values = ArrayUtil.append(values, oldValues);
883                             }
884                         }
885                     }
886 
887                     identifier = name;
888 
889                     name = QNameUtil.getPublicRenderParameterName(qName);
890 
891                     QNameUtil.setPublicRenderParameterIdentifier(
892                         name, identifier);
893                 }
894             }
895 
896             // LEP-7495
897 
898             //if (isBlankValue(values)) {
899             //  continue;
900             //}
901 
902             for (int i = 0; i < values.length; i++) {
903                 String parameterName = name;
904 
905                 if (identifier != null) {
906                     parameterName = identifier;
907                 }
908 
909                 if (isParameterIncludedInPath(parameterName)) {
910                     continue;
911                 }
912 
913                 if (!PortalUtil.isReservedParameter(name) &&
914                     !name.startsWith(
915                         QNameUtil.PUBLIC_RENDER_PARAMETER_NAMESPACE)) {
916 
917                     sb.append(getNamespace());
918                 }
919 
920                 sb.append(name);
921                 sb.append(StringPool.EQUAL);
922                 sb.append(processValue(key, values[i]));
923 
924                 if ((i + 1 < values.length) || itr.hasNext()) {
925                     sb.append(StringPool.AMPERSAND);
926                 }
927             }
928         }
929 
930         if (_encrypt) {
931             sb.append(StringPool.AMPERSAND + WebKeys.ENCRYPT + "=1");
932         }
933 
934         if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
935             if (_anchor && (_windowState != null) &&
936                 (!_windowState.equals(WindowState.MAXIMIZED)) &&
937                 (!_windowState.equals(LiferayWindowState.EXCLUSIVE)) &&
938                 (!_windowState.equals(LiferayWindowState.POP_UP))) {
939 
940                 if (sb.lastIndexOf(StringPool.AMPERSAND) != (sb.length() - 1)) {
941                     sb.append(StringPool.AMPERSAND);
942                 }
943 
944                 sb.append("#p_").append(_portletId);
945             }
946         }
947 
948         String result = sb.toString();
949 
950         if (result.endsWith(StringPool.AMPERSAND) ||
951             result.endsWith(StringPool.QUESTION)) {
952 
953             result = result.substring(0, result.length() - 1);
954         }
955 
956         if (themeDisplay.isFacebook()) {
957 
958             // Facebook requires the path portion of the URL to end with a slash
959 
960             int pos = result.indexOf(StringPool.QUESTION);
961 
962             if (pos == -1) {
963                 if (!result.endsWith(StringPool.SLASH)) {
964                     result += StringPool.SLASH;
965                 }
966             }
967             else {
968                 String path = result.substring(0, pos);
969 
970                 if (!result.endsWith(StringPool.SLASH)) {
971                     result = path + StringPool.SLASH + result.substring(pos);
972                 }
973             }
974         }
975 
976         if (!CookieKeys.hasSessionId(_request)) {
977             result = PortalUtil.getURLWithSessionId(
978                 result, _request.getSession().getId());
979         }
980 
981         if (_escapeXml) {
982             result = URLHelper.escapeURL(result);
983         }
984 
985         return result;
986     }
987 
988     protected boolean isBlankValue(String[] value) {
989         if ((value != null) && (value.length == 1) &&
990             (value[0].equals(StringPool.BLANK))) {
991 
992             return true;
993         }
994         else {
995             return false;
996         }
997     }
998 
999     protected String processValue(Key key, int value) {
1000        return processValue(key, String.valueOf(value));
1001    }
1002
1003    protected String processValue(Key key, long value) {
1004        return processValue(key, String.valueOf(value));
1005    }
1006
1007    protected String processValue(Key key, String value) {
1008        if (key == null) {
1009            return HttpUtil.encodeURL(value);
1010        }
1011        else {
1012            try {
1013                return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1014            }
1015            catch (EncryptorException ee) {
1016                return value;
1017            }
1018        }
1019    }
1020
1021    private static Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1022
1023    private HttpServletRequest _request;
1024    private PortletRequest _portletRequest;
1025    private String _portletId;
1026    private Portlet _portlet;
1027    private String _namespace;
1028    private long _plid;
1029    private Layout _layout;
1030    private String _layoutFriendlyURL;
1031    private String _lifecycle;
1032    private boolean _anchor = true;
1033    private String _cacheability = ResourceURL.PAGE;
1034    private boolean _copyCurrentPublicRenderParameters;
1035    private boolean _copyCurrentRenderParameters;
1036    private long _doAsUserId;
1037    private boolean _encrypt;
1038    private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1039    private Set<String> _parametersIncludedInPath;
1040    private Map<String, String[]> _params;
1041    private PortletMode _portletMode;
1042    private String _resourceID;
1043    private boolean _secure;
1044    private WindowState _windowState;
1045    private ChannelURLType _urlType;
1046    private String _toString;
1047
1048}