1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
29  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
30  import com.liferay.portal.kernel.portlet.LiferayWindowState;
31  import com.liferay.portal.kernel.portlet.PortletModeFactory;
32  import com.liferay.portal.kernel.portlet.WindowStateFactory;
33  import com.liferay.portal.kernel.util.ArrayUtil;
34  import com.liferay.portal.kernel.util.GetterUtil;
35  import com.liferay.portal.kernel.util.HtmlUtil;
36  import com.liferay.portal.kernel.util.Http;
37  import com.liferay.portal.kernel.util.HttpUtil;
38  import com.liferay.portal.kernel.util.MapUtil;
39  import com.liferay.portal.kernel.util.ParamUtil;
40  import com.liferay.portal.kernel.util.StringPool;
41  import com.liferay.portal.kernel.util.Validator;
42  import com.liferay.portal.kernel.xml.QName;
43  import com.liferay.portal.model.Company;
44  import com.liferay.portal.model.Layout;
45  import com.liferay.portal.model.Portlet;
46  import com.liferay.portal.model.PortletApp;
47  import com.liferay.portal.model.PublicRenderParameter;
48  import com.liferay.portal.service.LayoutLocalServiceUtil;
49  import com.liferay.portal.service.PortletLocalServiceUtil;
50  import com.liferay.portal.theme.PortletDisplay;
51  import com.liferay.portal.theme.ThemeDisplay;
52  import com.liferay.portal.util.CookieKeys;
53  import com.liferay.portal.util.PortalUtil;
54  import com.liferay.portal.util.PropsValues;
55  import com.liferay.portal.util.WebKeys;
56  import com.liferay.portlet.social.util.FacebookUtil;
57  import com.liferay.util.Encryptor;
58  import com.liferay.util.EncryptorException;
59  
60  import java.io.IOException;
61  import java.io.Serializable;
62  import java.io.Writer;
63  
64  import java.security.Key;
65  
66  import java.util.Enumeration;
67  import java.util.Iterator;
68  import java.util.LinkedHashMap;
69  import java.util.LinkedHashSet;
70  import java.util.Map;
71  import java.util.Set;
72  
73  import javax.portlet.PortletMode;
74  import javax.portlet.PortletModeException;
75  import javax.portlet.PortletRequest;
76  import javax.portlet.PortletURL;
77  import javax.portlet.ResourceRequest;
78  import javax.portlet.ResourceURL;
79  import javax.portlet.WindowState;
80  import javax.portlet.WindowStateException;
81  
82  import javax.servlet.http.HttpServletRequest;
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  public class PortletURLImpl
91      implements LiferayPortletURL, PortletURL, ResourceURL, Serializable {
92  
93      public PortletURLImpl(
94          HttpServletRequest request, String portletId, long plid,
95          String lifecycle) {
96  
97          _request = request;
98          _portletId = portletId;
99          _plid = plid;
100         _lifecycle = lifecycle;
101         _parametersIncludedInPath = new LinkedHashSet<String>();
102         _params = new LinkedHashMap<String, String[]>();
103         _removePublicRenderParameters = new LinkedHashMap<String, String[]>();
104         _secure = request.isSecure();
105         _wsrp = ParamUtil.getBoolean(request, "wsrp");
106 
107         Portlet portlet = getPortlet();
108 
109         if (portlet != null) {
110             PortletApp portletApp = portlet.getPortletApp();
111 
112             _escapeXml = MapUtil.getBoolean(
113                 portletApp.getContainerRuntimeOptions(),
114                 PortletConfigImpl.RUNTIME_OPTION_ESCAPE_XML,
115                 PropsValues.PORTLET_URL_ESCAPE_XML);
116         }
117     }
118 
119     public PortletURLImpl(
120         PortletRequestImpl portletRequestImpl, String portletId, long plid,
121         String lifecycle) {
122 
123         this(
124             portletRequestImpl.getHttpServletRequest(), portletId, plid,
125             lifecycle);
126 
127         _portletRequest = portletRequestImpl;
128     }
129 
130     public void addParameterIncludedInPath(String name) {
131         _parametersIncludedInPath.add(name);
132     }
133 
134     public void addProperty(String key, String value) {
135         if (key == null) {
136             throw new IllegalArgumentException();
137         }
138     }
139 
140     public String getCacheability() {
141         return _cacheability;
142     }
143 
144     public HttpServletRequest getHttpServletRequest() {
145         return _request;
146     }
147 
148     public Layout getLayout() {
149         if (_layout == null) {
150             try {
151                 if (_plid > 0) {
152                     _layout = LayoutLocalServiceUtil.getLayout(_plid);
153                 }
154             }
155             catch (Exception e) {
156                 if (_log.isWarnEnabled()) {
157                     _log.warn("Layout cannot be found for " + _plid);
158                 }
159             }
160         }
161 
162         return _layout;
163     }
164 
165     public String getLayoutFriendlyURL() {
166         return _layoutFriendlyURL;
167     }
168 
169     public String getLifecycle() {
170         return _lifecycle;
171     }
172 
173     public String getNamespace() {
174         if (_namespace == null) {
175             _namespace = PortalUtil.getPortletNamespace(_portletId);
176         }
177 
178         return _namespace;
179     }
180 
181     public String getParameter(String name) {
182         String[] values = _params.get(name);
183 
184         if ((values != null) && (values.length > 0)) {
185             return values[0];
186         }
187         else {
188             return null;
189         }
190     }
191 
192     public Map<String, String[]> getParameterMap() {
193         return _params;
194     }
195 
196     public Set<String> getParametersIncludedInPath() {
197         return _parametersIncludedInPath;
198     }
199 
200     public long getPlid() {
201         return _plid;
202     }
203 
204     public Portlet getPortlet() {
205         if (_portlet == null) {
206             try {
207                 _portlet = PortletLocalServiceUtil.getPortletById(
208                     PortalUtil.getCompanyId(_request), _portletId);
209             }
210             catch (SystemException se) {
211                 _log.error(se.getMessage());
212             }
213         }
214 
215         return _portlet;
216     }
217 
218     public String getPortletFriendlyURLPath() {
219         String portletFriendlyURLPath = null;
220 
221         Portlet portlet = getPortlet();
222 
223         if (portlet != null) {
224             FriendlyURLMapper mapper = portlet.getFriendlyURLMapperInstance();
225 
226             if (mapper != null) {
227                 portletFriendlyURLPath = mapper.buildPath(this);
228 
229                 if (_log.isDebugEnabled()) {
230                     _log.debug(
231                         "Portlet friendly URL path " + portletFriendlyURLPath);
232                 }
233             }
234         }
235 
236         return portletFriendlyURLPath;
237     }
238 
239     public String getPortletId() {
240         return _portletId;
241     }
242 
243     public PortletMode getPortletMode() {
244         return _portletMode;
245     }
246 
247     public PortletRequest getPortletRequest() {
248         return _portletRequest;
249     }
250 
251     public String getResourceID() {
252         return _resourceID;
253     }
254 
255     public WindowState getWindowState() {
256         return _windowState;
257     }
258 
259     public boolean isAnchor() {
260         return _anchor;
261     }
262 
263     public boolean isCopyCurrentPublicRenderParameters() {
264         return _copyCurrentPublicRenderParameters;
265     }
266 
267     public boolean isCopyCurrentRenderParameters() {
268         return _copyCurrentRenderParameters;
269     }
270 
271     public boolean isEncrypt() {
272         return _encrypt;
273     }
274 
275     public boolean isEscapeXml() {
276         return _escapeXml;
277     }
278 
279     public boolean isParameterIncludedInPath(String name) {
280         if (_parametersIncludedInPath.contains(name)) {
281             return true;
282         }
283         else {
284             return false;
285         }
286     }
287 
288     public boolean isSecure() {
289         return _secure;
290     }
291 
292     public void removePublicRenderParameter(String name) {
293         if (name == null) {
294             throw new IllegalArgumentException();
295         }
296 
297         PublicRenderParameter publicRenderParameter =
298             _portlet.getPublicRenderParameter(name);
299 
300         if (publicRenderParameter == null) {
301             if (_log.isWarnEnabled()) {
302                 _log.warn("Public parameter " + name + "does not exist");
303             }
304 
305             return;
306         }
307 
308         QName qName = publicRenderParameter.getQName();
309 
310         _removePublicRenderParameters.put(
311             PortletQNameUtil.getRemovePublicRenderParameterName(qName),
312             new String[] {"1"});
313     }
314 
315     public void setAnchor(boolean anchor) {
316         _anchor = anchor;
317 
318         // Clear cache
319 
320         _toString = null;
321     }
322 
323     public void setCacheability(String cacheability) {
324         if (cacheability == null) {
325             throw new IllegalArgumentException("Cacheability is null");
326         }
327 
328         if (!cacheability.equals(FULL) && !cacheability.equals(PORTLET) &&
329             !cacheability.equals(PAGE)) {
330 
331             throw new IllegalArgumentException(
332                 "Cacheability " + cacheability + " is not " + FULL + ", " +
333                     PORTLET + ", or " + PAGE);
334         }
335 
336         if (_portletRequest instanceof ResourceRequest) {
337             ResourceRequest resourceRequest = (ResourceRequest)_portletRequest;
338 
339             String parentCacheability = resourceRequest.getCacheability();
340 
341             if (parentCacheability.equals(FULL)) {
342                 if (!cacheability.equals(FULL)) {
343                     throw new IllegalStateException(
344                         "Unable to set a weaker cacheability " + cacheability);
345                 }
346             }
347             else if (parentCacheability.equals(PORTLET)) {
348                 if (!cacheability.equals(FULL) &&
349                     !cacheability.equals(PORTLET)) {
350 
351                     throw new IllegalStateException(
352                         "Unable to set a weaker cacheability " + cacheability);
353                 }
354             }
355         }
356 
357         _cacheability = cacheability;
358 
359         // Clear cache
360 
361         _toString = null;
362     }
363 
364     public void setCopyCurrentPublicRenderParameters(
365         boolean copyCurrentPublicRenderParameters) {
366 
367         _copyCurrentPublicRenderParameters = copyCurrentPublicRenderParameters;
368     }
369 
370     public void setCopyCurrentRenderParameters(
371         boolean copyCurrentRenderParameters) {
372 
373         _copyCurrentRenderParameters = copyCurrentRenderParameters;
374     }
375 
376     public void setDoAsGroupId(long doAsGroupId) {
377         _doAsGroupId = doAsGroupId;
378 
379         // Clear cache
380 
381         _toString = null;
382     }
383 
384     public void setDoAsUserId(long doAsUserId) {
385         _doAsUserId = doAsUserId;
386 
387         // Clear cache
388 
389         _toString = null;
390     }
391 
392     public void setDoAsUserLanguageId(String doAsUserLanguageId) {
393         _doAsUserLanguageId = doAsUserLanguageId;
394 
395         // Clear cache
396 
397         _toString = null;
398     }
399 
400     public void setEncrypt(boolean encrypt) {
401         _encrypt = encrypt;
402 
403         // Clear cache
404 
405         _toString = null;
406     }
407 
408     public void setEscapeXml(boolean escapeXml) {
409         _escapeXml = escapeXml;
410 
411         // Clear cache
412 
413         _toString = null;
414     }
415 
416     public void setLifecycle(String lifecycle) {
417         _lifecycle = lifecycle;
418 
419         // Clear cache
420 
421         _toString = null;
422     }
423 
424     public void setParameter(String name, String value) {
425         setParameter(name, value, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
426     }
427 
428     public void setParameter(String name, String value, boolean append) {
429         if ((name == null) || (value == null)) {
430             throw new IllegalArgumentException();
431         }
432 
433         setParameter(name, new String[] {value}, append);
434     }
435 
436     public void setParameter(String name, String[] values) {
437         setParameter(name, values, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
438     }
439 
440     public void setParameter(String name, String[] values, boolean append) {
441         if ((name == null) || (values == null)) {
442             throw new IllegalArgumentException();
443         }
444 
445         for (int i = 0; i < values.length; i++) {
446             if (values[i] == null) {
447                 throw new IllegalArgumentException();
448             }
449         }
450 
451         if (append && _params.containsKey(name)) {
452             String[] oldValues = _params.get(name);
453 
454             String[] newValues = ArrayUtil.append(oldValues, values);
455 
456             _params.put(name, newValues);
457         }
458         else {
459             _params.put(name, values);
460         }
461 
462         // Clear cache
463 
464         _toString = null;
465     }
466 
467     public void setParameters(Map<String, String[]> params) {
468         if (params == null) {
469             throw new IllegalArgumentException();
470         }
471         else {
472             Map<String, String[]> newParams =
473                 new LinkedHashMap<String, String[]>();
474 
475             for (Map.Entry<String, String[]> entry : params.entrySet()) {
476                 try {
477                     String key = entry.getKey();
478                     String[] value = entry.getValue();
479 
480                     if (key == null) {
481                         throw new IllegalArgumentException();
482                     }
483                     else if (value == null) {
484                         throw new IllegalArgumentException();
485                     }
486 
487                     newParams.put(key, value);
488                 }
489                 catch (ClassCastException cce) {
490                     throw new IllegalArgumentException(cce);
491                 }
492             }
493 
494             _params = newParams;
495         }
496 
497         // Clear cache
498 
499         _toString = null;
500     }
501 
502     public void setPlid(long plid) {
503         _plid = plid;
504 
505         // Clear cache
506 
507         _toString = null;
508     }
509 
510     public void setPortletId(String portletId) {
511         _portletId = portletId;
512 
513         // Clear cache
514 
515         _toString = null;
516     }
517 
518     public void setPortletMode(PortletMode portletMode)
519         throws PortletModeException {
520 
521         if (_portletRequest != null) {
522             if (!getPortlet().hasPortletMode(
523                     _portletRequest.getResponseContentType(), portletMode)) {
524 
525                 throw new PortletModeException(
526                     portletMode.toString(), portletMode);
527             }
528         }
529 
530         _portletMode = portletMode;
531 
532         // Clear cache
533 
534         _toString = null;
535     }
536 
537     public void setPortletMode(String portletMode) throws PortletModeException {
538         setPortletMode(PortletModeFactory.getPortletMode(portletMode));
539     }
540 
541     public void setProperty(String key, String value) {
542         if (key == null) {
543             throw new IllegalArgumentException();
544         }
545     }
546 
547     public void setRefererPlid(long refererPlid) {
548         _refererPlid = refererPlid;
549 
550         // Clear cache
551 
552         _toString = null;
553     }
554 
555     public void setResourceID(String resourceID) {
556         _resourceID = resourceID;
557     }
558 
559     public void setSecure(boolean secure) {
560         _secure = secure;
561 
562         // Clear cache
563 
564         _toString = null;
565     }
566 
567     public void setWindowState(String windowState) throws WindowStateException {
568         setWindowState(WindowStateFactory.getWindowState(windowState));
569     }
570 
571     public void setWindowState(WindowState windowState)
572         throws WindowStateException {
573 
574         if (_portletRequest != null) {
575             if (!_portletRequest.isWindowStateAllowed(windowState)) {
576                 throw new WindowStateException(
577                     windowState.toString(), windowState);
578             }
579         }
580 
581         if (LiferayWindowState.isWindowStatePreserved(
582                 getWindowState(), windowState)) {
583 
584             _windowState = windowState;
585         }
586 
587         // Clear cache
588 
589         _toString = null;
590     }
591 
592     public String toString() {
593         if (_toString != null) {
594             return _toString;
595         }
596 
597         if (_wsrp) {
598             _toString = generateWSRPToString();
599         }
600         else {
601             _toString = generateToString();
602         }
603 
604         return _toString;
605     }
606 
607     public void write(Writer writer) throws IOException {
608         write(writer, _escapeXml);
609     }
610 
611     public void write(Writer writer, boolean escapeXml) throws IOException {
612         String toString = toString();
613 
614         if (escapeXml && !_escapeXml) {
615             toString = HtmlUtil.escape(toString);
616         }
617 
618         writer.write(toString);
619     }
620 
621     protected String generateToString() {
622         StringBuilder sb = new StringBuilder();
623 
624         ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
625             WebKeys.THEME_DISPLAY);
626 
627         PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
628 
629         Portlet portlet = getPortlet();
630 
631         String portalURL = null;
632 
633         if (themeDisplay.isFacebook()) {
634             portalURL =
635                 FacebookUtil.FACEBOOK_APPS_URL +
636                     themeDisplay.getFacebookCanvasPageURL();
637         }
638         else {
639             portalURL = PortalUtil.getPortalURL(_request, _secure);
640         }
641 
642         try {
643             if (_layoutFriendlyURL == null) {
644                 Layout layout = getLayout();
645 
646                 if (layout != null) {
647                     _layoutFriendlyURL = GetterUtil.getString(
648                         PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
649                 }
650             }
651         }
652         catch (Exception e) {
653             _log.error(e);
654         }
655 
656         Key key = null;
657 
658         try {
659             if (_encrypt) {
660                 Company company = PortalUtil.getCompany(_request);
661 
662                 key = company.getKeyObj();
663             }
664         }
665         catch (Exception e) {
666             _log.error(e);
667         }
668 
669         if (Validator.isNull(_layoutFriendlyURL)) {
670             sb.append(portalURL);
671             sb.append(themeDisplay.getPathMain());
672             sb.append("/portal/layout?");
673 
674             sb.append("p_l_id");
675             sb.append(StringPool.EQUAL);
676             sb.append(processValue(key, _plid));
677             sb.append(StringPool.AMPERSAND);
678         }
679         else {
680 
681             // A virtual host URL will contain the complete path. Do not append
682             // the portal URL if the virtual host URL starts with "http://" or
683             // "https://".
684 
685             if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
686                 !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
687 
688                 sb.append(portalURL);
689             }
690 
691             if (!themeDisplay.isFacebook()) {
692                 sb.append(_layoutFriendlyURL);
693             }
694 
695             String friendlyURLPath = getPortletFriendlyURLPath();
696 
697             if (Validator.isNotNull(friendlyURLPath)) {
698                 if (themeDisplay.isFacebook()) {
699                     int pos = friendlyURLPath.indexOf(StringPool.SLASH, 1);
700 
701                     if (pos != -1) {
702                         sb.append(friendlyURLPath.substring(pos));
703                     }
704                     else {
705                         sb.append(friendlyURLPath);
706                     }
707                 }
708                 else {
709                     sb.append("/-");
710                     sb.append(friendlyURLPath);
711                 }
712 
713                 if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
714                     addParameterIncludedInPath("p_p_lifecycle");
715                 }
716 
717                 //if ((_windowState != null) &&
718                 //  _windowState.equals(WindowState.MAXIMIZED)) {
719 
720                     addParameterIncludedInPath("p_p_state");
721                 //}
722 
723                 //if ((_portletMode != null) &&
724                 //  _portletMode.equals(PortletMode.VIEW)) {
725 
726                     addParameterIncludedInPath("p_p_mode");
727                 //}
728 
729                 addParameterIncludedInPath("p_p_col_id");
730                 addParameterIncludedInPath("p_p_col_pos");
731                 addParameterIncludedInPath("p_p_col_count");
732             }
733 
734             sb.append(StringPool.QUESTION);
735         }
736 
737         if (!isParameterIncludedInPath("p_p_id")) {
738             sb.append("p_p_id");
739             sb.append(StringPool.EQUAL);
740             sb.append(processValue(key, _portletId));
741             sb.append(StringPool.AMPERSAND);
742         }
743 
744         if (!isParameterIncludedInPath("p_p_lifecycle")) {
745             sb.append("p_p_lifecycle");
746             sb.append(StringPool.EQUAL);
747 
748             if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
749                 sb.append(processValue(key, "1"));
750             }
751             else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
752                 sb.append(processValue(key, "0"));
753             }
754             else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
755                 sb.append(processValue(key, "2"));
756             }
757 
758             sb.append(StringPool.AMPERSAND);
759         }
760 
761         if (!isParameterIncludedInPath("p_p_state")) {
762             if (_windowState != null) {
763                 sb.append("p_p_state");
764                 sb.append(StringPool.EQUAL);
765                 sb.append(processValue(key, _windowState.toString()));
766                 sb.append(StringPool.AMPERSAND);
767             }
768         }
769 
770         if (!isParameterIncludedInPath("p_p_mode")) {
771             if (_portletMode != null) {
772                 sb.append("p_p_mode");
773                 sb.append(StringPool.EQUAL);
774                 sb.append(processValue(key, _portletMode.toString()));
775                 sb.append(StringPool.AMPERSAND);
776             }
777         }
778 
779         if (!isParameterIncludedInPath("p_p_resource_id")) {
780             if (_resourceID != null) {
781                 sb.append("p_p_resource_id");
782                 sb.append(StringPool.EQUAL);
783                 sb.append(processValue(key, _resourceID));
784                 sb.append(StringPool.AMPERSAND);
785             }
786         }
787 
788         if (!isParameterIncludedInPath("p_p_cacheability")) {
789             if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
790                 sb.append("p_p_cacheability");
791                 sb.append(StringPool.EQUAL);
792                 sb.append(processValue(key, _cacheability));
793                 sb.append(StringPool.AMPERSAND);
794             }
795         }
796 
797         if (!isParameterIncludedInPath("p_p_col_id")) {
798             if (Validator.isNotNull(portletDisplay.getColumnId())) {
799                 sb.append("p_p_col_id");
800                 sb.append(StringPool.EQUAL);
801                 sb.append(processValue(key, portletDisplay.getColumnId()));
802                 sb.append(StringPool.AMPERSAND);
803             }
804         }
805 
806         if (!isParameterIncludedInPath("p_p_col_pos")) {
807             if (portletDisplay.getColumnPos() > 0) {
808                 sb.append("p_p_col_pos");
809                 sb.append(StringPool.EQUAL);
810                 sb.append(processValue(key, portletDisplay.getColumnPos()));
811                 sb.append(StringPool.AMPERSAND);
812             }
813         }
814 
815         if (!isParameterIncludedInPath("p_p_col_count")) {
816             if (portletDisplay.getColumnCount() > 0) {
817                 sb.append("p_p_col_count");
818                 sb.append(StringPool.EQUAL);
819                 sb.append(processValue(key, portletDisplay.getColumnCount()));
820                 sb.append(StringPool.AMPERSAND);
821             }
822         }
823 
824         if (_doAsUserId > 0) {
825             try {
826                 Company company = PortalUtil.getCompany(_request);
827 
828                 sb.append("doAsUserId");
829                 sb.append(StringPool.EQUAL);
830                 sb.append(processValue(company.getKeyObj(), _doAsUserId));
831                 sb.append(StringPool.AMPERSAND);
832             }
833             catch (Exception e) {
834                 _log.error(e);
835             }
836         }
837         else {
838             String doAsUserId = themeDisplay.getDoAsUserId();
839 
840             if (Validator.isNotNull(doAsUserId)) {
841                 sb.append("doAsUserId");
842                 sb.append(StringPool.EQUAL);
843                 sb.append(processValue(key, doAsUserId));
844                 sb.append(StringPool.AMPERSAND);
845             }
846         }
847 
848         String doAsUserLanguageId = _doAsUserLanguageId;
849 
850         if (Validator.isNull(doAsUserLanguageId)) {
851             doAsUserLanguageId = themeDisplay.getDoAsUserLanguageId();
852         }
853 
854         if (Validator.isNotNull(doAsUserLanguageId)) {
855             sb.append("doAsUserLanguageId");
856             sb.append(StringPool.EQUAL);
857             sb.append(processValue(key, doAsUserLanguageId));
858             sb.append(StringPool.AMPERSAND);
859         }
860 
861         long doAsGroupId = _doAsGroupId;
862 
863         if (doAsGroupId <= 0) {
864             doAsGroupId = themeDisplay.getDoAsGroupId();
865         }
866 
867         if (doAsGroupId > 0) {
868             sb.append("doAsGroupId");
869             sb.append(StringPool.EQUAL);
870             sb.append(processValue(key, doAsGroupId));
871             sb.append(StringPool.AMPERSAND);
872         }
873 
874         long refererPlid = _refererPlid;
875 
876         if (refererPlid <= 0) {
877             refererPlid = themeDisplay.getRefererPlid();
878         }
879 
880         if (refererPlid > 0) {
881             sb.append("refererPlid");
882             sb.append(StringPool.EQUAL);
883             sb.append(processValue(key, refererPlid));
884             sb.append(StringPool.AMPERSAND);
885         }
886 
887         Iterator<Map.Entry<String, String[]>> itr =
888             _removePublicRenderParameters.entrySet().iterator();
889 
890         while (itr.hasNext()) {
891             if (sb.lastIndexOf(StringPool.AMPERSAND) != (sb.length() - 1)) {
892                 sb.append(StringPool.AMPERSAND);
893             }
894 
895             Map.Entry<String, String[]> entry = itr.next();
896 
897             sb.append(entry.getKey());
898             sb.append(StringPool.EQUAL);
899             sb.append(processValue(key, entry.getValue()[0]));
900             sb.append(StringPool.AMPERSAND);
901         }
902 
903         if (_copyCurrentRenderParameters) {
904             Enumeration<String> enu = _request.getParameterNames();
905 
906             while (enu.hasMoreElements()) {
907                 String name = enu.nextElement();
908 
909                 String[] oldValues = _request.getParameterValues(name);
910                 String[] newValues = _params.get(name);
911 
912                 if (newValues == null) {
913                     _params.put(name, oldValues);
914                 }
915                 else if (isBlankValue(newValues)) {
916                     _params.remove(name);
917                 }
918                 else {
919                     newValues = ArrayUtil.append(newValues, oldValues);
920 
921                     _params.put(name, newValues);
922                 }
923             }
924         }
925 
926         itr = _params.entrySet().iterator();
927 
928         while (itr.hasNext()) {
929             Map.Entry<String, String[]> entry = itr.next();
930 
931             String name = entry.getKey();
932             String[] values = entry.getValue();
933 
934             String identifier = null;
935 
936             if (portlet != null) {
937                 PublicRenderParameter publicRenderParameter =
938                     portlet.getPublicRenderParameter(name);
939 
940                 if (publicRenderParameter != null) {
941                     QName qName = publicRenderParameter.getQName();
942 
943                     if (_copyCurrentPublicRenderParameters) {
944                         String[] oldValues = _request.getParameterValues(name);
945 
946                         if (oldValues != null) {
947                             if (values == null) {
948                                 values = oldValues;
949                             }
950                             else {
951                                 values = ArrayUtil.append(values, oldValues);
952                             }
953                         }
954                     }
955 
956                     identifier = name;
957 
958                     name = PortletQNameUtil.getPublicRenderParameterName(qName);
959 
960                     PortletQNameUtil.setPublicRenderParameterIdentifier(
961                         name, identifier);
962                 }
963             }
964 
965             // LEP-7495
966 
967             //if (isBlankValue(values)) {
968             //  continue;
969             //}
970 
971             for (int i = 0; i < values.length; i++) {
972                 String parameterName = name;
973 
974                 if (identifier != null) {
975                     parameterName = identifier;
976                 }
977 
978                 if (isParameterIncludedInPath(parameterName)) {
979                     continue;
980                 }
981 
982                 if (!PortalUtil.isReservedParameter(name) &&
983                     !name.startsWith(
984                         PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE)) {
985 
986                     sb.append(getNamespace());
987                 }
988 
989                 sb.append(name);
990                 sb.append(StringPool.EQUAL);
991                 sb.append(processValue(key, values[i]));
992 
993                 if ((i + 1 < values.length) || itr.hasNext()) {
994                     sb.append(StringPool.AMPERSAND);
995                 }
996             }
997         }
998 
999         if (_encrypt) {
1000            sb.append(StringPool.AMPERSAND + WebKeys.ENCRYPT + "=1");
1001        }
1002
1003        if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1004            if (_anchor && (_windowState != null) &&
1005                (!_windowState.equals(WindowState.MAXIMIZED)) &&
1006                (!_windowState.equals(LiferayWindowState.EXCLUSIVE)) &&
1007                (!_windowState.equals(LiferayWindowState.POP_UP))) {
1008
1009                if (sb.lastIndexOf(StringPool.AMPERSAND) != (sb.length() - 1)) {
1010                    sb.append(StringPool.AMPERSAND);
1011                }
1012
1013                sb.append("#p_").append(_portletId);
1014            }
1015        }
1016
1017        String result = sb.toString();
1018
1019        if (result.endsWith(StringPool.AMPERSAND) ||
1020            result.endsWith(StringPool.QUESTION)) {
1021
1022            result = result.substring(0, result.length() - 1);
1023        }
1024
1025        if (themeDisplay.isFacebook()) {
1026
1027            // Facebook requires the path portion of the URL to end with a slash
1028
1029            int pos = result.indexOf(StringPool.QUESTION);
1030
1031            if (pos == -1) {
1032                if (!result.endsWith(StringPool.SLASH)) {
1033                    result += StringPool.SLASH;
1034                }
1035            }
1036            else {
1037                String path = result.substring(0, pos);
1038
1039                if (!result.endsWith(StringPool.SLASH)) {
1040                    result = path + StringPool.SLASH + result.substring(pos);
1041                }
1042            }
1043        }
1044
1045        if (!CookieKeys.hasSessionId(_request)) {
1046            result = PortalUtil.getURLWithSessionId(
1047                result, _request.getSession().getId());
1048        }
1049
1050        if (_escapeXml) {
1051            result = HtmlUtil.escape(result);
1052        }
1053
1054        return result;
1055    }
1056
1057    protected String generateWSRPToString() {
1058        StringBuilder sb = new StringBuilder("wsrp_rewrite?");
1059
1060        Portlet portlet = getPortlet();
1061
1062        Key key = null;
1063
1064        try {
1065            if (_encrypt) {
1066                Company company = PortalUtil.getCompany(_request);
1067
1068                key = company.getKeyObj();
1069            }
1070        }
1071        catch (Exception e) {
1072            _log.error(e);
1073        }
1074
1075        sb.append("wsrp-urlType");
1076        sb.append(StringPool.EQUAL);
1077
1078        if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
1079            sb.append(processValue(key, "blockingAction"));
1080        }
1081        else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
1082            sb.append(processValue(key, "render"));
1083        }
1084        else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1085            sb.append(processValue(key, "resource"));
1086        }
1087
1088        sb.append(StringPool.AMPERSAND);
1089
1090        if (_windowState != null) {
1091            sb.append("wsrp-windowState");
1092            sb.append(StringPool.EQUAL);
1093            sb.append(processValue(key, "wsrp:" + _windowState.toString()));
1094            sb.append(StringPool.AMPERSAND);
1095        }
1096
1097        if (_portletMode != null) {
1098            sb.append("wsrp-mode");
1099            sb.append(StringPool.EQUAL);
1100            sb.append(processValue(key, "wsrp:" + _portletMode.toString()));
1101            sb.append(StringPool.AMPERSAND);
1102        }
1103
1104        if (_resourceID != null) {
1105            sb.append("wsrp-resourceID");
1106            sb.append(StringPool.EQUAL);
1107            sb.append(processValue(key, _resourceID));
1108            sb.append(StringPool.AMPERSAND);
1109        }
1110
1111        if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1112            sb.append("wsrp-resourceCacheability");
1113            sb.append(StringPool.EQUAL);
1114            sb.append(processValue(key, _cacheability));
1115            sb.append(StringPool.AMPERSAND);
1116        }
1117
1118        if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1119            if (_anchor && (_windowState != null) &&
1120                (!_windowState.equals(WindowState.MAXIMIZED)) &&
1121                (!_windowState.equals(LiferayWindowState.EXCLUSIVE)) &&
1122                (!_windowState.equals(LiferayWindowState.POP_UP))) {
1123
1124                sb.append("wsrp-fragmentID");
1125                sb.append(StringPool.EQUAL);
1126                sb.append("#p_").append(_portletId);
1127                sb.append(StringPool.AMPERSAND);
1128            }
1129        }
1130
1131        if (_copyCurrentRenderParameters) {
1132            Enumeration<String> enu = _request.getParameterNames();
1133
1134            while (enu.hasMoreElements()) {
1135                String name = enu.nextElement();
1136
1137                String[] oldValues = _request.getParameterValues(name);
1138                String[] newValues = _params.get(name);
1139
1140                if (newValues == null) {
1141                    _params.put(name, oldValues);
1142                }
1143                else if (isBlankValue(newValues)) {
1144                    _params.remove(name);
1145                }
1146                else {
1147                    newValues = ArrayUtil.append(newValues, oldValues);
1148
1149                    _params.put(name, newValues);
1150                }
1151            }
1152        }
1153
1154        StringBuilder parameterSb = new StringBuilder();
1155
1156        Iterator<Map.Entry<String, String[]>> itr =
1157            _params.entrySet().iterator();
1158
1159        while (itr.hasNext()) {
1160            Map.Entry<String, String[]> entry = itr.next();
1161
1162            String name = entry.getKey();
1163            String[] values = entry.getValue();
1164
1165            String identifier = null;
1166
1167            if (portlet != null) {
1168                PublicRenderParameter publicRenderParameter =
1169                    portlet.getPublicRenderParameter(name);
1170
1171                if (publicRenderParameter != null) {
1172                    QName qName = publicRenderParameter.getQName();
1173
1174                    if (_copyCurrentPublicRenderParameters) {
1175                        String[] oldValues = _request.getParameterValues(name);
1176
1177                        if (oldValues != null) {
1178                            if (values == null) {
1179                                values = oldValues;
1180                            }
1181                            else {
1182                                values = ArrayUtil.append(values, oldValues);
1183                            }
1184                        }
1185                    }
1186
1187                    identifier = name;
1188
1189                    name = PortletQNameUtil.getPublicRenderParameterName(qName);
1190
1191                    PortletQNameUtil.setPublicRenderParameterIdentifier(
1192                        name, identifier);
1193                }
1194            }
1195
1196            for (int i = 0; i < values.length; i++) {
1197                String parameterName = name;
1198
1199                if (identifier != null) {
1200                    parameterName = identifier;
1201                }
1202
1203                if (isParameterIncludedInPath(parameterName)) {
1204                    continue;
1205                }
1206
1207                if (!PortalUtil.isReservedParameter(name) &&
1208                    !name.startsWith(
1209                        PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE)) {
1210
1211                    parameterSb.append(getNamespace());
1212                }
1213
1214                parameterSb.append(name);
1215                parameterSb.append(StringPool.EQUAL);
1216                parameterSb.append(processValue(key, values[i]));
1217
1218                if ((i + 1 < values.length) || itr.hasNext()) {
1219                    parameterSb.append(StringPool.AMPERSAND);
1220                }
1221            }
1222        }
1223
1224        if (_encrypt) {
1225            parameterSb.append(StringPool.AMPERSAND + WebKeys.ENCRYPT + "=1");
1226        }
1227
1228        sb.append("wsrp-navigationalState");
1229        sb.append(StringPool.EQUAL);
1230        sb.append(HttpUtil.encodeURL(parameterSb.toString()));
1231
1232        sb.append("/wsrp_rewrite");
1233
1234        return sb.toString();
1235    }
1236
1237    protected boolean isBlankValue(String[] value) {
1238        if ((value != null) && (value.length == 1) &&
1239            (value[0].equals(StringPool.BLANK))) {
1240
1241            return true;
1242        }
1243        else {
1244            return false;
1245        }
1246    }
1247
1248    protected String processValue(Key key, int value) {
1249        return processValue(key, String.valueOf(value));
1250    }
1251
1252    protected String processValue(Key key, long value) {
1253        return processValue(key, String.valueOf(value));
1254    }
1255
1256    protected String processValue(Key key, String value) {
1257        if (key == null) {
1258            return HttpUtil.encodeURL(value);
1259        }
1260        else {
1261            try {
1262                return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1263            }
1264            catch (EncryptorException ee) {
1265                return value;
1266            }
1267        }
1268    }
1269
1270    private static Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1271
1272    private boolean _anchor = true;
1273    private String _cacheability = ResourceURL.PAGE;
1274    private boolean _copyCurrentPublicRenderParameters;
1275    private boolean _copyCurrentRenderParameters;
1276    private long _doAsGroupId;
1277    private long _doAsUserId;
1278    private String _doAsUserLanguageId;
1279    private boolean _encrypt;
1280    private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1281    private Layout _layout;
1282    private String _layoutFriendlyURL;
1283    private String _lifecycle;
1284    private String _namespace;
1285    private Set<String> _parametersIncludedInPath;
1286    private Map<String, String[]> _params;
1287    private long _plid;
1288    private Portlet _portlet;
1289    private String _portletId;
1290    private PortletMode _portletMode;
1291    private PortletRequest _portletRequest;
1292    private long _refererPlid;
1293    private Map<String, String[]> _removePublicRenderParameters;
1294    private HttpServletRequest _request;
1295    private String _resourceID;
1296    private boolean _secure;
1297    private String _toString;
1298    private WindowState _windowState;
1299    private boolean _wsrp;
1300
1301}