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