001
014
015 package com.liferay.portlet;
016
017 import com.liferay.portal.kernel.exception.SystemException;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
021 import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
022 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
023 import com.liferay.portal.kernel.portlet.LiferayWindowState;
024 import com.liferay.portal.kernel.portlet.PortletModeFactory;
025 import com.liferay.portal.kernel.portlet.WindowStateFactory;
026 import com.liferay.portal.kernel.util.ArrayUtil;
027 import com.liferay.portal.kernel.util.Base64;
028 import com.liferay.portal.kernel.util.CharPool;
029 import com.liferay.portal.kernel.util.GetterUtil;
030 import com.liferay.portal.kernel.util.HtmlUtil;
031 import com.liferay.portal.kernel.util.Http;
032 import com.liferay.portal.kernel.util.HttpUtil;
033 import com.liferay.portal.kernel.util.MapUtil;
034 import com.liferay.portal.kernel.util.ParamUtil;
035 import com.liferay.portal.kernel.util.StringBundler;
036 import com.liferay.portal.kernel.util.StringPool;
037 import com.liferay.portal.kernel.util.Validator;
038 import com.liferay.portal.kernel.xml.QName;
039 import com.liferay.portal.model.Company;
040 import com.liferay.portal.model.Layout;
041 import com.liferay.portal.model.Portlet;
042 import com.liferay.portal.model.PortletApp;
043 import com.liferay.portal.model.PublicRenderParameter;
044 import com.liferay.portal.model.impl.VirtualLayout;
045 import com.liferay.portal.security.auth.AuthTokenUtil;
046 import com.liferay.portal.security.lang.DoPrivilegedUtil;
047 import com.liferay.portal.service.LayoutLocalServiceUtil;
048 import com.liferay.portal.service.PortletLocalServiceUtil;
049 import com.liferay.portal.theme.PortletDisplay;
050 import com.liferay.portal.theme.ThemeDisplay;
051 import com.liferay.portal.util.CookieKeys;
052 import com.liferay.portal.util.PortalUtil;
053 import com.liferay.portal.util.PortletKeys;
054 import com.liferay.portal.util.PropsValues;
055 import com.liferay.portal.util.WebKeys;
056 import com.liferay.portlet.social.util.FacebookUtil;
057 import com.liferay.util.Encryptor;
058 import com.liferay.util.EncryptorException;
059
060 import java.io.IOException;
061 import java.io.Serializable;
062 import java.io.UnsupportedEncodingException;
063 import java.io.Writer;
064
065 import java.security.Key;
066 import java.security.PrivilegedAction;
067
068 import java.util.Collections;
069 import java.util.Iterator;
070 import java.util.LinkedHashMap;
071 import java.util.LinkedHashSet;
072 import java.util.Map;
073 import java.util.Set;
074
075 import javax.portlet.PortletMode;
076 import javax.portlet.PortletModeException;
077 import javax.portlet.PortletRequest;
078 import javax.portlet.PortletURL;
079 import javax.portlet.ResourceRequest;
080 import javax.portlet.ResourceURL;
081 import javax.portlet.WindowState;
082 import javax.portlet.WindowStateException;
083
084 import javax.servlet.http.HttpServletRequest;
085
086
091 public class PortletURLImpl
092 implements LiferayPortletURL, PortletURL, ResourceURL, Serializable {
093
094 public PortletURLImpl(
095 HttpServletRequest request, String portletId, long plid,
096 String lifecycle) {
097
098 _request = request;
099 _portletId = portletId;
100 _plid = plid;
101 _lifecycle = lifecycle;
102 _parametersIncludedInPath = new LinkedHashSet<String>();
103 _params = new LinkedHashMap<String, String[]>();
104 _removePublicRenderParameters = new LinkedHashMap<String, String[]>();
105 _secure = PortalUtil.isSecure(request);
106 _wsrp = ParamUtil.getBoolean(request, "wsrp");
107
108 Portlet portlet = getPortlet();
109
110 if (portlet != null) {
111 Set<String> autopropagatedParameters =
112 portlet.getAutopropagatedParameters();
113
114 for (String autopropagatedParameter : autopropagatedParameters) {
115 if (PortalUtil.isReservedParameter(autopropagatedParameter)) {
116 continue;
117 }
118
119 String value = request.getParameter(autopropagatedParameter);
120
121 if (value != null) {
122 setParameter(autopropagatedParameter, value);
123 }
124 }
125
126 PortletApp portletApp = portlet.getPortletApp();
127
128 _escapeXml = MapUtil.getBoolean(
129 portletApp.getContainerRuntimeOptions(),
130 LiferayPortletConfig.RUNTIME_OPTION_ESCAPE_XML,
131 PropsValues.PORTLET_URL_ESCAPE_XML);
132 }
133
134 Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
135
136 if ((layout != null) && (layout.getPlid() == _plid) &&
137 (layout instanceof VirtualLayout)) {
138
139 _layout = layout;
140 }
141 }
142
143 public PortletURLImpl(
144 PortletRequest portletRequest, String portletId, long plid,
145 String lifecycle) {
146
147 this(
148 PortalUtil.getHttpServletRequest(portletRequest), portletId, plid,
149 lifecycle);
150
151 _portletRequest = portletRequest;
152 }
153
154 @Override
155 public void addParameterIncludedInPath(String name) {
156 _parametersIncludedInPath.add(name);
157 }
158
159 @Override
160 public void addProperty(String key, String value) {
161 if (key == null) {
162 throw new IllegalArgumentException();
163 }
164 }
165
166 @Override
167 public String getCacheability() {
168 return _cacheability;
169 }
170
171 public HttpServletRequest getHttpServletRequest() {
172 return _request;
173 }
174
175 public Layout getLayout() {
176 if (_layout == null) {
177 try {
178 if (_plid > 0) {
179 _layout = LayoutLocalServiceUtil.getLayout(_plid);
180 }
181 }
182 catch (Exception e) {
183 if (_log.isWarnEnabled()) {
184 _log.warn("Layout cannot be found for " + _plid);
185 }
186 }
187 }
188
189 return _layout;
190 }
191
192 public String getLayoutFriendlyURL() {
193 return _layoutFriendlyURL;
194 }
195
196 @Override
197 public String getLifecycle() {
198 return _lifecycle;
199 }
200
201 public String getNamespace() {
202 if (_namespace == null) {
203 _namespace = PortalUtil.getPortletNamespace(_portletId);
204 }
205
206 return _namespace;
207 }
208
209 @Override
210 public String getParameter(String name) {
211 String[] values = _params.get(name);
212
213 if ((values != null) && (values.length > 0)) {
214 return values[0];
215 }
216 else {
217 return null;
218 }
219 }
220
221 @Override
222 public Map<String, String[]> getParameterMap() {
223 return _params;
224 }
225
226 @Override
227 public Set<String> getParametersIncludedInPath() {
228 return _parametersIncludedInPath;
229 }
230
231 public long getPlid() {
232 return _plid;
233 }
234
235 public Portlet getPortlet() {
236 if (_portlet == null) {
237 try {
238 _portlet = PortletLocalServiceUtil.getPortletById(
239 PortalUtil.getCompanyId(_request), _portletId);
240 }
241 catch (SystemException se) {
242 _log.error(se.getMessage());
243 }
244 }
245
246 return _portlet;
247 }
248
249 public String getPortletFriendlyURLPath() {
250 String portletFriendlyURLPath = null;
251
252 Portlet portlet = getPortlet();
253
254 if (portlet != null) {
255 FriendlyURLMapper mapper = portlet.getFriendlyURLMapperInstance();
256
257 if (mapper != null) {
258 portletFriendlyURLPath = mapper.buildPath(this);
259
260 if (_log.isDebugEnabled()) {
261 _log.debug(
262 "Portlet friendly URL path " + portletFriendlyURLPath);
263 }
264 }
265 }
266
267 return portletFriendlyURLPath;
268 }
269
270 @Override
271 public String getPortletId() {
272 return _portletId;
273 }
274
275 @Override
276 public PortletMode getPortletMode() {
277 if (_portletModeString == null) {
278 return null;
279 }
280
281 return PortletModeFactory.getPortletMode(_portletModeString);
282 }
283
284 public PortletRequest getPortletRequest() {
285 return _portletRequest;
286 }
287
288 @Override
289 public Set<String> getRemovedParameterNames() {
290 return _removedParameterNames;
291 }
292
293 @Override
294 public Map<String, String> getReservedParameterMap() {
295 if (_reservedParameters != null) {
296 return _reservedParameters;
297 }
298
299 _reservedParameters = new LinkedHashMap<String, String>();
300
301 _reservedParameters.put("p_p_id", _portletId);
302
303 if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
304 _reservedParameters.put("p_p_lifecycle", "1");
305 }
306 else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
307 _reservedParameters.put("p_p_lifecycle", "0");
308 }
309 else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
310 _reservedParameters.put("p_p_lifecycle", "2");
311 }
312
313 if (_windowStateString != null) {
314 _reservedParameters.put("p_p_state", _windowStateString);
315 }
316
317 if (_windowStateRestoreCurrentView) {
318 _reservedParameters.put("p_p_state_rcv", "1");
319 }
320
321 if (_portletModeString != null) {
322 _reservedParameters.put("p_p_mode", _portletModeString);
323 }
324
325 if (_resourceID != null) {
326 _reservedParameters.put("p_p_resource_id", _resourceID);
327 }
328
329 if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
330 _reservedParameters.put("p_p_cacheability", _cacheability);
331 }
332
333 ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
334 WebKeys.THEME_DISPLAY);
335
336 PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
337
338 if (Validator.isNotNull(portletDisplay.getColumnId())) {
339 _reservedParameters.put("p_p_col_id", portletDisplay.getColumnId());
340 }
341
342 if (portletDisplay.getColumnPos() > 0) {
343 _reservedParameters.put(
344 "p_p_col_pos", String.valueOf(portletDisplay.getColumnPos()));
345 }
346
347 if (portletDisplay.getColumnCount() > 0) {
348 _reservedParameters.put(
349 "p_p_col_count",
350 String.valueOf(portletDisplay.getColumnCount()));
351 }
352
353 _reservedParameters = Collections.unmodifiableMap(_reservedParameters);
354
355 return _reservedParameters;
356 }
357
358 @Override
359 public String getResourceID() {
360 return _resourceID;
361 }
362
363 @Override
364 public WindowState getWindowState() {
365 if (_windowStateString == null) {
366 return null;
367 }
368
369 return WindowStateFactory.getWindowState(_windowStateString);
370 }
371
372 @Override
373 public boolean isAnchor() {
374 return _anchor;
375 }
376
377 @Override
378 public boolean isCopyCurrentRenderParameters() {
379 return _copyCurrentRenderParameters;
380 }
381
382 @Override
383 public boolean isEncrypt() {
384 return _encrypt;
385 }
386
387 @Override
388 public boolean isEscapeXml() {
389 return _escapeXml;
390 }
391
392 @Override
393 public boolean isParameterIncludedInPath(String name) {
394 if (_parametersIncludedInPath.contains(name)) {
395 return true;
396 }
397 else {
398 return false;
399 }
400 }
401
402 @Override
403 public boolean isSecure() {
404 return _secure;
405 }
406
407 @Override
408 public void removePublicRenderParameter(String name) {
409 if (name == null) {
410 throw new IllegalArgumentException();
411 }
412
413 PublicRenderParameter publicRenderParameter =
414 _portlet.getPublicRenderParameter(name);
415
416 if (publicRenderParameter == null) {
417 if (_log.isWarnEnabled()) {
418 _log.warn("Public parameter " + name + "does not exist");
419 }
420
421 return;
422 }
423
424 QName qName = publicRenderParameter.getQName();
425
426 _removePublicRenderParameters.put(
427 PortletQNameUtil.getRemovePublicRenderParameterName(qName),
428 new String[] {"1"});
429 }
430
431 @Override
432 public void setAnchor(boolean anchor) {
433 _anchor = anchor;
434
435 clearCache();
436 }
437
438 @Override
439 public void setCacheability(String cacheability) {
440 if (cacheability == null) {
441 throw new IllegalArgumentException("Cacheability is null");
442 }
443
444 if (!cacheability.equals(FULL) && !cacheability.equals(PORTLET) &&
445 !cacheability.equals(PAGE)) {
446
447 throw new IllegalArgumentException(
448 "Cacheability " + cacheability + " is not " + FULL + ", " +
449 PORTLET + ", or " + PAGE);
450 }
451
452 if (_portletRequest instanceof ResourceRequest) {
453 ResourceRequest resourceRequest = (ResourceRequest)_portletRequest;
454
455 String parentCacheability = resourceRequest.getCacheability();
456
457 if (parentCacheability.equals(FULL)) {
458 if (!cacheability.equals(FULL)) {
459 throw new IllegalStateException(
460 "Unable to set a weaker cacheability " + cacheability);
461 }
462 }
463 else if (parentCacheability.equals(PORTLET)) {
464 if (!cacheability.equals(FULL) &&
465 !cacheability.equals(PORTLET)) {
466
467 throw new IllegalStateException(
468 "Unable to set a weaker cacheability " + cacheability);
469 }
470 }
471 }
472
473 _cacheability = cacheability;
474
475 clearCache();
476 }
477
478 @Override
479 public void setControlPanelCategory(String controlPanelCategory) {
480 _controlPanelCategory = controlPanelCategory;
481
482 clearCache();
483 }
484
485 @Override
486 public void setCopyCurrentRenderParameters(
487 boolean copyCurrentRenderParameters) {
488
489 _copyCurrentRenderParameters = copyCurrentRenderParameters;
490 }
491
492 @Override
493 public void setDoAsGroupId(long doAsGroupId) {
494 _doAsGroupId = doAsGroupId;
495
496 clearCache();
497 }
498
499 @Override
500 public void setDoAsUserId(long doAsUserId) {
501 _doAsUserId = doAsUserId;
502
503 clearCache();
504 }
505
506 @Override
507 public void setDoAsUserLanguageId(String doAsUserLanguageId) {
508 _doAsUserLanguageId = doAsUserLanguageId;
509
510 clearCache();
511 }
512
513 @Override
514 public void setEncrypt(boolean encrypt) {
515 _encrypt = encrypt;
516
517 clearCache();
518 }
519
520 @Override
521 public void setEscapeXml(boolean escapeXml) {
522 _escapeXml = escapeXml;
523
524 clearCache();
525 }
526
527 @Override
528 public void setLifecycle(String lifecycle) {
529 _lifecycle = lifecycle;
530
531 clearCache();
532 }
533
534 @Override
535 public void setParameter(String name, String value) {
536 setParameter(name, value, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
537 }
538
539 @Override
540 public void setParameter(String name, String value, boolean append) {
541 if ((name == null) || (value == null)) {
542 throw new IllegalArgumentException();
543 }
544
545 setParameter(name, new String[] {value}, append);
546 }
547
548 @Override
549 public void setParameter(String name, String[] values) {
550 setParameter(name, values, PropsValues.PORTLET_URL_APPEND_PARAMETERS);
551 }
552
553 @Override
554 public void setParameter(String name, String[] values, boolean append) {
555 if ((name == null) || (values == null)) {
556 throw new IllegalArgumentException();
557 }
558
559 for (String value : values) {
560 if (value == null) {
561 throw new IllegalArgumentException();
562 }
563 }
564
565 if (!append) {
566 _params.put(name, values);
567 }
568 else {
569 String[] oldValues = _params.get(name);
570
571 if (oldValues == null) {
572 _params.put(name, values);
573 }
574 else {
575 String[] newValues = ArrayUtil.append(oldValues, values);
576
577 _params.put(name, newValues);
578 }
579 }
580
581 clearCache();
582 }
583
584 @Override
585 public void setParameters(Map<String, String[]> params) {
586 if (params == null) {
587 throw new IllegalArgumentException();
588 }
589 else {
590 Map<String, String[]> newParams =
591 new LinkedHashMap<String, String[]>();
592
593 for (Map.Entry<String, String[]> entry : params.entrySet()) {
594 try {
595 String key = entry.getKey();
596 String[] value = entry.getValue();
597
598 if (key == null) {
599 throw new IllegalArgumentException();
600 }
601 else if (value == null) {
602 throw new IllegalArgumentException();
603 }
604
605 newParams.put(key, value);
606 }
607 catch (ClassCastException cce) {
608 throw new IllegalArgumentException(cce);
609 }
610 }
611
612 _params = newParams;
613 }
614
615 clearCache();
616 }
617
618 @Override
619 public void setPlid(long plid) {
620 _plid = plid;
621
622 clearCache();
623 }
624
625 @Override
626 public void setPortletId(String portletId) {
627 _portletId = portletId;
628
629 clearCache();
630 }
631
632 @Override
633 public void setPortletMode(PortletMode portletMode)
634 throws PortletModeException {
635
636 if (_portletRequest != null) {
637 if (!getPortlet().hasPortletMode(
638 _portletRequest.getResponseContentType(), portletMode)) {
639
640 throw new PortletModeException(
641 portletMode.toString(), portletMode);
642 }
643 }
644
645 _portletModeString = portletMode.toString();
646
647 clearCache();
648 }
649
650 public void setPortletMode(String portletMode) throws PortletModeException {
651 setPortletMode(PortletModeFactory.getPortletMode(portletMode));
652 }
653
654 @Override
655 public void setProperty(String key, String value) {
656 if (key == null) {
657 throw new IllegalArgumentException();
658 }
659 }
660
661 public void setRefererGroupId(long refererGroupId) {
662 _refererGroupId = refererGroupId;
663
664 clearCache();
665 }
666
667 @Override
668 public void setRefererPlid(long refererPlid) {
669 _refererPlid = refererPlid;
670
671 clearCache();
672 }
673
674 @Override
675 public void setRemovedParameterNames(Set<String> removedParameterNames) {
676 _removedParameterNames = removedParameterNames;
677
678 clearCache();
679 }
680
681 @Override
682 public void setResourceID(String resourceID) {
683 _resourceID = resourceID;
684 }
685
686 @Override
687 public void setSecure(boolean secure) {
688 _secure = secure;
689
690 clearCache();
691 }
692
693 public void setWindowState(String windowState) throws WindowStateException {
694 setWindowState(WindowStateFactory.getWindowState(windowState));
695 }
696
697 @Override
698 public void setWindowState(WindowState windowState)
699 throws WindowStateException {
700
701 if (_portletRequest != null) {
702 if (!_portletRequest.isWindowStateAllowed(windowState)) {
703 throw new WindowStateException(
704 windowState.toString(), windowState);
705 }
706 }
707
708 if (LiferayWindowState.isWindowStatePreserved(
709 getWindowState(), windowState)) {
710
711 _windowStateString = windowState.toString();
712 }
713
714 clearCache();
715 }
716
717 public void setWindowStateRestoreCurrentView(
718 boolean windowStateRestoreCurrentView) {
719
720 _windowStateRestoreCurrentView = windowStateRestoreCurrentView;
721 }
722
723 @Override
724 public String toString() {
725 if (_toString != null) {
726 return _toString;
727 }
728
729 _toString = DoPrivilegedUtil.wrap(new ToStringPrivilegedAction());
730
731 return _toString;
732 }
733
734 @Override
735 public void write(Writer writer) throws IOException {
736 write(writer, _escapeXml);
737 }
738
739 @Override
740 public void write(Writer writer, boolean escapeXml) throws IOException {
741 String toString = toString();
742
743 if (escapeXml && !_escapeXml) {
744 toString = HtmlUtil.escape(toString);
745 }
746
747 writer.write(toString);
748 }
749
750 protected void addPortalAuthToken(StringBundler sb, Key key) {
751 if (!PropsValues.AUTH_TOKEN_CHECK_ENABLED ||
752 !_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
753
754 return;
755 }
756
757 Set<String> authTokenIgnorePortlets =
758 PortalUtil.getAuthTokenIgnorePortlets();
759
760 if (authTokenIgnorePortlets.contains(_portletId)) {
761 return;
762 }
763
764 sb.append("p_auth");
765 sb.append(StringPool.EQUAL);
766 sb.append(processValue(key, AuthTokenUtil.getToken(_request)));
767 sb.append(StringPool.AMPERSAND);
768 }
769
770 protected void addPortletAuthToken(StringBundler sb, Key key) {
771 if (!PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED) {
772 return;
773 }
774
775 HttpServletRequest request = PortalUtil.getOriginalServletRequest(
776 _request);
777
778 String ppauth = ParamUtil.getString(request, "p_p_auth");
779
780 String actualPortletAuthenticationToken = AuthTokenUtil.getToken(
781 _request, _plid, _portletId);
782
783 if (Validator.isNotNull(ppauth) &&
784 ppauth.equals(actualPortletAuthenticationToken)) {
785
786 sb.append("p_p_auth");
787 sb.append(StringPool.EQUAL);
788 sb.append(processValue(key, ppauth));
789 sb.append(StringPool.AMPERSAND);
790
791 return;
792 }
793
794 if (!_portlet.isAddDefaultResource()) {
795 return;
796 }
797
798 Portlet portlet = (Portlet)_request.getAttribute(
799 WebKeys.RENDER_PORTLET);
800
801 if (portlet != null) {
802 String portletId = portlet.getPortletId();
803
804 if (portletId.equals(_portletId) ||
805 portletId.equals(PortletKeys.CONTROL_PANEL_MENU)) {
806
807 return;
808 }
809 }
810
811 Set<String> portletAddDefaultResourceCheckWhiteList =
812 PortalUtil.getPortletAddDefaultResourceCheckWhitelist();
813
814 if (portletAddDefaultResourceCheckWhiteList.contains(_portletId)) {
815 return;
816 }
817
818 sb.append("p_p_auth");
819 sb.append(StringPool.EQUAL);
820 sb.append(processValue(key, actualPortletAuthenticationToken));
821 sb.append(StringPool.AMPERSAND);
822 }
823
824 protected void clearCache() {
825 _reservedParameters = null;
826 _toString = null;
827 }
828
829 protected String generateToString() {
830 StringBundler sb = new StringBundler(64);
831
832 ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
833 WebKeys.THEME_DISPLAY);
834
835 String portalURL = null;
836
837 if (themeDisplay.isFacebook()) {
838 portalURL =
839 FacebookUtil.FACEBOOK_APPS_URL +
840 themeDisplay.getFacebookCanvasPageURL();
841 }
842 else {
843 portalURL = PortalUtil.getPortalURL(_request, _secure);
844 }
845
846 try {
847 if (_layoutFriendlyURL == null) {
848 Layout layout = getLayout();
849
850 if (layout != null) {
851 _layoutFriendlyURL = GetterUtil.getString(
852 PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
853
854 if (_secure) {
855 _layoutFriendlyURL = HttpUtil.protocolize(
856 _layoutFriendlyURL, true);
857 }
858 }
859 }
860 }
861 catch (Exception e) {
862 _log.error(e);
863 }
864
865 Key key = null;
866
867 try {
868 if (_encrypt) {
869 Company company = PortalUtil.getCompany(_request);
870
871 key = company.getKeyObj();
872 }
873 }
874 catch (Exception e) {
875 _log.error(e);
876 }
877
878 if (Validator.isNull(_layoutFriendlyURL)) {
879 sb.append(portalURL);
880 sb.append(themeDisplay.getPathMain());
881 sb.append("/portal/layout?");
882
883 addPortalAuthToken(sb, key);
884
885 sb.append("p_l_id");
886 sb.append(StringPool.EQUAL);
887 sb.append(processValue(key, _plid));
888 sb.append(StringPool.AMPERSAND);
889 }
890 else {
891 if (themeDisplay.isFacebook()) {
892 sb.append(portalURL);
893 }
894 else {
895
896
897
898
899
900 if (!_layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
901 !_layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
902
903 sb.append(portalURL);
904 }
905
906 sb.append(_layoutFriendlyURL);
907 }
908
909 String friendlyURLPath = getPortletFriendlyURLPath();
910
911 if (Validator.isNotNull(friendlyURLPath)) {
912 if (themeDisplay.isFacebook()) {
913 int pos = friendlyURLPath.indexOf(CharPool.SLASH, 1);
914
915 if (pos != -1) {
916 sb.append(friendlyURLPath.substring(pos));
917 }
918 else {
919 sb.append(friendlyURLPath);
920 }
921 }
922 else {
923 sb.append("/-");
924 sb.append(friendlyURLPath);
925 }
926 }
927
928 sb.append(StringPool.QUESTION);
929
930 addPortalAuthToken(sb, key);
931 }
932
933 addPortletAuthToken(sb, key);
934
935 for (Map.Entry<String, String> entry :
936 getReservedParameterMap().entrySet()) {
937
938 String name = entry.getKey();
939
940 if (!isParameterIncludedInPath(name)) {
941 sb.append(HttpUtil.encodeURL(name));
942 sb.append(StringPool.EQUAL);
943 sb.append(processValue(key, entry.getValue()));
944 sb.append(StringPool.AMPERSAND);
945 }
946 }
947
948 if (_doAsUserId > 0) {
949 try {
950 Company company = PortalUtil.getCompany(_request);
951
952 sb.append("doAsUserId");
953 sb.append(StringPool.EQUAL);
954 sb.append(processValue(company.getKeyObj(), _doAsUserId));
955 sb.append(StringPool.AMPERSAND);
956 }
957 catch (Exception e) {
958 _log.error(e);
959 }
960 }
961 else {
962 String doAsUserId = themeDisplay.getDoAsUserId();
963
964 if (Validator.isNotNull(doAsUserId)) {
965 sb.append("doAsUserId");
966 sb.append(StringPool.EQUAL);
967 sb.append(processValue(key, doAsUserId));
968 sb.append(StringPool.AMPERSAND);
969 }
970 }
971
972 String doAsUserLanguageId = _doAsUserLanguageId;
973
974 if (Validator.isNull(doAsUserLanguageId)) {
975 doAsUserLanguageId = themeDisplay.getDoAsUserLanguageId();
976 }
977
978 if (Validator.isNotNull(doAsUserLanguageId)) {
979 sb.append("doAsUserLanguageId");
980 sb.append(StringPool.EQUAL);
981 sb.append(processValue(key, doAsUserLanguageId));
982 sb.append(StringPool.AMPERSAND);
983 }
984
985 long doAsGroupId = _doAsGroupId;
986
987 if (doAsGroupId <= 0) {
988 doAsGroupId = themeDisplay.getDoAsGroupId();
989 }
990
991 if (doAsGroupId > 0) {
992 sb.append("doAsGroupId");
993 sb.append(StringPool.EQUAL);
994 sb.append(processValue(key, doAsGroupId));
995 sb.append(StringPool.AMPERSAND);
996 }
997
998 long refererGroupId = _refererGroupId;
999
1000 if (refererGroupId <= 0) {
1001 refererGroupId = themeDisplay.getRefererGroupId();
1002 }
1003
1004 if (refererGroupId > 0) {
1005 sb.append("refererGroupId");
1006 sb.append(StringPool.EQUAL);
1007 sb.append(processValue(key, refererGroupId));
1008 sb.append(StringPool.AMPERSAND);
1009 }
1010
1011 long refererPlid = _refererPlid;
1012
1013 if (refererPlid <= 0) {
1014 refererPlid = themeDisplay.getRefererPlid();
1015 }
1016
1017 if (refererPlid > 0) {
1018 sb.append("refererPlid");
1019 sb.append(StringPool.EQUAL);
1020 sb.append(processValue(key, refererPlid));
1021 sb.append(StringPool.AMPERSAND);
1022 }
1023
1024 String controlPanelCategory = _controlPanelCategory;
1025
1026 if (Validator.isNull(controlPanelCategory)) {
1027 controlPanelCategory = themeDisplay.getControlPanelCategory();
1028 }
1029
1030 if (Validator.isNotNull(controlPanelCategory)) {
1031 sb.append("controlPanelCategory");
1032 sb.append(StringPool.EQUAL);
1033 sb.append(processValue(key, controlPanelCategory));
1034 sb.append(StringPool.AMPERSAND);
1035 }
1036
1037 Iterator<Map.Entry<String, String[]>> itr =
1038 _removePublicRenderParameters.entrySet().iterator();
1039
1040 while (itr.hasNext()) {
1041 String lastString = sb.stringAt(sb.index() - 1);
1042
1043 if (lastString.charAt(lastString.length() - 1) !=
1044 CharPool.AMPERSAND) {
1045
1046 sb.append(StringPool.AMPERSAND);
1047 }
1048
1049 Map.Entry<String, String[]> entry = itr.next();
1050
1051 sb.append(HttpUtil.encodeURL(entry.getKey()));
1052 sb.append(StringPool.EQUAL);
1053 sb.append(processValue(key, entry.getValue()[0]));
1054 sb.append(StringPool.AMPERSAND);
1055 }
1056
1057 if (_copyCurrentRenderParameters) {
1058 mergeRenderParameters();
1059 }
1060
1061 itr = _params.entrySet().iterator();
1062
1063 while (itr.hasNext()) {
1064 Map.Entry<String, String[]> entry = itr.next();
1065
1066 String name = entry.getKey();
1067 String[] values = entry.getValue();
1068
1069 if (isParameterIncludedInPath(name)) {
1070 continue;
1071 }
1072
1073 String publicRenderParameterName = getPublicRenderParameterName(
1074 name);
1075
1076 if (Validator.isNotNull(publicRenderParameterName)) {
1077 name = publicRenderParameterName;
1078 }
1079
1080 name = HttpUtil.encodeURL(prependNamespace(name));
1081
1082 for (int i = 0; i < values.length; i++) {
1083 sb.append(name);
1084 sb.append(StringPool.EQUAL);
1085 sb.append(processValue(key, values[i]));
1086
1087 if (((i + 1) < values.length) || itr.hasNext()) {
1088 sb.append(StringPool.AMPERSAND);
1089 }
1090 }
1091 }
1092
1093 if (_encrypt) {
1094 sb.append(StringPool.AMPERSAND + WebKeys.ENCRYPT + "=1");
1095 }
1096
1097 if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1098 if (_anchor && (_windowStateString != null) &&
1099 !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1100 !_windowStateString.equals(
1101 LiferayWindowState.EXCLUSIVE.toString()) &&
1102 !_windowStateString.equals(
1103 LiferayWindowState.POP_UP.toString())) {
1104
1105 String lastString = sb.stringAt(sb.index() - 1);
1106
1107 if (lastString.charAt(lastString.length() - 1) !=
1108 CharPool.AMPERSAND) {
1109
1110 sb.append(StringPool.AMPERSAND);
1111 }
1112
1113 sb.append("#p_");
1114 sb.append(HttpUtil.encodeURL(_portletId));
1115 }
1116 }
1117
1118 String result = sb.toString();
1119
1120 if (result.endsWith(StringPool.AMPERSAND) ||
1121 result.endsWith(StringPool.QUESTION)) {
1122
1123 result = result.substring(0, result.length() - 1);
1124 }
1125
1126 if (themeDisplay.isFacebook()) {
1127
1128
1129
1130 int pos = result.indexOf(CharPool.QUESTION);
1131
1132 if (pos == -1) {
1133 if (!result.endsWith(StringPool.SLASH)) {
1134 result += StringPool.SLASH;
1135 }
1136 }
1137 else {
1138 String path = result.substring(0, pos);
1139
1140 if (!result.endsWith(StringPool.SLASH)) {
1141 result = path + StringPool.SLASH + result.substring(pos);
1142 }
1143 }
1144 }
1145 else if (!CookieKeys.hasSessionId(_request)) {
1146 result = PortalUtil.getURLWithSessionId(
1147 result, _request.getSession().getId());
1148 }
1149
1150 if (_escapeXml) {
1151 result = HtmlUtil.escape(result);
1152 }
1153
1154 if (result.length() > _URL_MAXIMUM_LENGTH) {
1155 result = shortenURL(result, 2);
1156 }
1157
1158 return result;
1159 }
1160
1161 protected String generateWSRPToString() {
1162 StringBundler sb = new StringBundler("wsrp_rewrite?");
1163
1164 sb.append("wsrp-urlType");
1165 sb.append(StringPool.EQUAL);
1166
1167 if (_lifecycle.equals(PortletRequest.ACTION_PHASE)) {
1168 sb.append(HttpUtil.encodeURL("blockingAction"));
1169 }
1170 else if (_lifecycle.equals(PortletRequest.RENDER_PHASE)) {
1171 sb.append(HttpUtil.encodeURL("render"));
1172 }
1173 else if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1174 sb.append(HttpUtil.encodeURL("resource"));
1175 }
1176
1177 sb.append(StringPool.AMPERSAND);
1178
1179 if (_windowStateString != null) {
1180 sb.append("wsrp-windowState");
1181 sb.append(StringPool.EQUAL);
1182 sb.append(HttpUtil.encodeURL("wsrp:" + _windowStateString));
1183 sb.append(StringPool.AMPERSAND);
1184 }
1185
1186 if (_portletModeString != null) {
1187 sb.append("wsrp-mode");
1188 sb.append(StringPool.EQUAL);
1189 sb.append(HttpUtil.encodeURL("wsrp:" + _portletModeString));
1190 sb.append(StringPool.AMPERSAND);
1191 }
1192
1193 if (_resourceID != null) {
1194 sb.append("wsrp-resourceID");
1195 sb.append(StringPool.EQUAL);
1196 sb.append(HttpUtil.encodeURL(_resourceID));
1197 sb.append(StringPool.AMPERSAND);
1198 }
1199
1200 if (_lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
1201 sb.append("wsrp-resourceCacheability");
1202 sb.append(StringPool.EQUAL);
1203 sb.append(HttpUtil.encodeURL(_cacheability));
1204 sb.append(StringPool.AMPERSAND);
1205 }
1206
1207 if (PropsValues.PORTLET_URL_ANCHOR_ENABLE) {
1208 if (_anchor && (_windowStateString != null) &&
1209 !_windowStateString.equals(WindowState.MAXIMIZED.toString()) &&
1210 !_windowStateString.equals(
1211 LiferayWindowState.EXCLUSIVE.toString()) &&
1212 !_windowStateString.equals(
1213 LiferayWindowState.POP_UP.toString())) {
1214
1215 sb.append("wsrp-fragmentID");
1216 sb.append(StringPool.EQUAL);
1217 sb.append("#p_");
1218 sb.append(HttpUtil.encodeURL(_portletId));
1219 sb.append(StringPool.AMPERSAND);
1220 }
1221 }
1222
1223 if (_copyCurrentRenderParameters) {
1224 mergeRenderParameters();
1225 }
1226
1227 StringBundler parameterSb = new StringBundler();
1228
1229 Iterator<Map.Entry<String, String[]>> itr =
1230 _params.entrySet().iterator();
1231
1232 while (itr.hasNext()) {
1233 Map.Entry<String, String[]> entry = itr.next();
1234
1235 String name = entry.getKey();
1236 String[] values = entry.getValue();
1237
1238 if (isParameterIncludedInPath(name)) {
1239 continue;
1240 }
1241
1242 String publicRenderParameterName = getPublicRenderParameterName(
1243 name);
1244
1245 if (Validator.isNotNull(publicRenderParameterName)) {
1246 name = publicRenderParameterName;
1247 }
1248
1249 name = HttpUtil.encodeURL(prependNamespace(name));
1250
1251 for (int i = 0; i < values.length; i++) {
1252 parameterSb.append(name);
1253 parameterSb.append(StringPool.EQUAL);
1254 parameterSb.append(HttpUtil.encodeURL(values[i]));
1255
1256 if (((i + 1) < values.length) || itr.hasNext()) {
1257 parameterSb.append(StringPool.AMPERSAND);
1258 }
1259 }
1260 }
1261
1262 sb.append("wsrp-navigationalState");
1263 sb.append(StringPool.EQUAL);
1264
1265 byte[] parameterBytes = null;
1266
1267 try {
1268 String parameterString = parameterSb.toString();
1269
1270 parameterBytes = parameterString.getBytes(StringPool.UTF8);
1271 }
1272 catch (UnsupportedEncodingException uee) {
1273 if (_log.isWarnEnabled()) {
1274 _log.warn(uee, uee);
1275 }
1276 }
1277
1278 String navigationalState = Base64.toURLSafe(
1279 Base64.encode(parameterBytes));
1280
1281 sb.append(navigationalState);
1282
1283 sb.append("/wsrp_rewrite");
1284
1285 return sb.toString();
1286 }
1287
1288 protected String getPublicRenderParameterName(String name) {
1289 Portlet portlet = getPortlet();
1290
1291 String publicRenderParameterName = null;
1292
1293 if (portlet != null) {
1294 PublicRenderParameter publicRenderParameter =
1295 portlet.getPublicRenderParameter(name);
1296
1297 if (publicRenderParameter != null) {
1298 QName qName = publicRenderParameter.getQName();
1299
1300 publicRenderParameterName =
1301 PortletQNameUtil.getPublicRenderParameterName(qName);
1302 }
1303 }
1304
1305 return publicRenderParameterName;
1306 }
1307
1308 protected boolean isBlankValue(String[] value) {
1309 if ((value != null) && (value.length == 1) &&
1310 value[0].equals(StringPool.BLANK)) {
1311
1312 return true;
1313 }
1314 else {
1315 return false;
1316 }
1317 }
1318
1319 protected void mergeRenderParameters() {
1320 String namespace = getNamespace();
1321
1322 Layout layout = getLayout();
1323
1324 Map<String, String[]> renderParameters = RenderParametersPool.get(
1325 _request, layout.getPlid(), getPortlet().getPortletId());
1326
1327 for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
1328 String name = entry.getKey();
1329
1330 if (name.contains(namespace)) {
1331 name = name.substring(namespace.length());
1332 }
1333
1334 if (!_lifecycle.equals(PortletRequest.RESOURCE_PHASE) &&
1335 (_removedParameterNames != null) &&
1336 _removedParameterNames.contains(name)) {
1337
1338 continue;
1339 }
1340
1341 String[] oldValues = entry.getValue();
1342 String[] newValues = _params.get(name);
1343
1344 if (newValues == null) {
1345 _params.put(name, oldValues);
1346 }
1347 else if (isBlankValue(newValues)) {
1348 _params.remove(name);
1349 }
1350 else {
1351 newValues = ArrayUtil.append(newValues, oldValues);
1352
1353 _params.put(name, newValues);
1354 }
1355 }
1356 }
1357
1358 protected String prependNamespace(String name) {
1359 String namespace = getNamespace();
1360
1361 if (!PortalUtil.isReservedParameter(name) &&
1362 !name.startsWith(PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE) &&
1363 !name.startsWith(namespace)) {
1364
1365 return namespace.concat(name);
1366 }
1367 else {
1368 return name;
1369 }
1370 }
1371
1372 protected String processValue(Key key, int value) {
1373 return processValue(key, String.valueOf(value));
1374 }
1375
1376 protected String processValue(Key key, long value) {
1377 return processValue(key, String.valueOf(value));
1378 }
1379
1380 protected String processValue(Key key, String value) {
1381 if (key == null) {
1382 return HttpUtil.encodeURL(value);
1383 }
1384 else {
1385 try {
1386 return HttpUtil.encodeURL(Encryptor.encrypt(key, value));
1387 }
1388 catch (EncryptorException ee) {
1389 return value;
1390 }
1391 }
1392 }
1393
1394 protected String shortenURL(String url, int count) {
1395 if (count == 0) {
1396 return null;
1397 }
1398
1399 StringBundler sb = new StringBundler();
1400
1401 String[] params = url.split(StringPool.AMPERSAND);
1402
1403 for (int i = 0; i < params.length; i++) {
1404 String param = params[i];
1405
1406 if (param.contains("_backURL=") || param.contains("_redirect=") ||
1407 param.contains("_returnToFullPageURL=")) {
1408
1409 int pos = param.indexOf(StringPool.EQUAL);
1410
1411 String qName = param.substring(0, pos);
1412
1413 String redirect = param.substring(pos + 1);
1414
1415 redirect = HttpUtil.decodeURL(redirect);
1416
1417 String newURL = shortenURL(redirect, count - 1);
1418
1419 if (newURL != null) {
1420 newURL = HttpUtil.encodeURL(newURL);
1421
1422 sb.append(qName);
1423 sb.append(StringPool.EQUAL);
1424 sb.append(newURL);
1425
1426 if (i < (params.length - 1)) {
1427 sb.append(StringPool.AMPERSAND);
1428 }
1429 }
1430 }
1431 else {
1432 sb.append(param);
1433
1434 if (i < (params.length - 1)) {
1435 sb.append(StringPool.AMPERSAND);
1436 }
1437 }
1438 }
1439
1440 return sb.toString();
1441 }
1442
1443 private static final long _URL_MAXIMUM_LENGTH = 2083;
1444
1445 private static Log _log = LogFactoryUtil.getLog(PortletURLImpl.class);
1446
1447 private boolean _anchor = true;
1448 private String _cacheability = ResourceURL.PAGE;
1449 private String _controlPanelCategory;
1450 private boolean _copyCurrentRenderParameters;
1451 private long _doAsGroupId;
1452 private long _doAsUserId;
1453 private String _doAsUserLanguageId;
1454 private boolean _encrypt;
1455 private boolean _escapeXml = PropsValues.PORTLET_URL_ESCAPE_XML;
1456 private Layout _layout;
1457 private String _layoutFriendlyURL;
1458 private String _lifecycle;
1459 private String _namespace;
1460 private Set<String> _parametersIncludedInPath;
1461 private Map<String, String[]> _params;
1462 private long _plid;
1463 private Portlet _portlet;
1464 private String _portletId;
1465 private String _portletModeString;
1466 private PortletRequest _portletRequest;
1467 private long _refererGroupId;
1468 private long _refererPlid;
1469 private Set<String> _removedParameterNames;
1470 private Map<String, String[]> _removePublicRenderParameters;
1471 private HttpServletRequest _request;
1472 private Map<String, String> _reservedParameters;
1473 private String _resourceID;
1474 private boolean _secure;
1475 private String _toString;
1476 private boolean _windowStateRestoreCurrentView;
1477 private String _windowStateString;
1478 private boolean _wsrp;
1479
1480 private class ToStringPrivilegedAction implements PrivilegedAction<String> {
1481
1482 @Override
1483 public String run() {
1484 if (_wsrp) {
1485 return generateWSRPToString();
1486 }
1487
1488 return generateToString();
1489 }
1490 }
1491
1492 }