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