001
014
015 package com.liferay.portlet;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
023 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
024 import com.liferay.portal.kernel.servlet.URLEncoder;
025 import com.liferay.portal.kernel.util.ArrayUtil;
026 import com.liferay.portal.kernel.util.GetterUtil;
027 import com.liferay.portal.kernel.util.ParamUtil;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.kernel.util.WebKeys;
031 import com.liferay.portal.model.Layout;
032 import com.liferay.portal.model.LayoutConstants;
033 import com.liferay.portal.model.Portlet;
034 import com.liferay.portal.model.PortletApp;
035 import com.liferay.portal.model.PortletURLListener;
036 import com.liferay.portal.security.lang.DoPrivilegedUtil;
037 import com.liferay.portal.security.xml.SecureXMLFactoryProviderUtil;
038 import com.liferay.portal.service.LayoutLocalServiceUtil;
039 import com.liferay.portal.service.PortletLocalServiceUtil;
040 import com.liferay.portal.struts.StrutsActionPortletURL;
041 import com.liferay.portal.theme.ThemeDisplay;
042 import com.liferay.portal.util.PortalUtil;
043 import com.liferay.portal.util.PropsValues;
044
045 import java.io.Writer;
046
047 import java.lang.reflect.Constructor;
048
049 import java.security.PrivilegedAction;
050
051 import java.util.ArrayList;
052 import java.util.LinkedHashMap;
053 import java.util.List;
054 import java.util.Map;
055 import java.util.Set;
056 import java.util.concurrent.ConcurrentHashMap;
057
058 import javax.portlet.MimeResponse;
059 import javax.portlet.PortletException;
060 import javax.portlet.PortletModeException;
061 import javax.portlet.PortletPreferences;
062 import javax.portlet.PortletRequest;
063 import javax.portlet.PortletResponse;
064 import javax.portlet.PortletURL;
065 import javax.portlet.PortletURLGenerationListener;
066 import javax.portlet.ResourceURL;
067 import javax.portlet.WindowStateException;
068 import javax.portlet.filter.PortletResponseWrapper;
069
070 import javax.servlet.http.Cookie;
071 import javax.servlet.http.HttpServletRequest;
072 import javax.servlet.http.HttpServletResponse;
073
074 import javax.xml.parsers.DocumentBuilder;
075 import javax.xml.parsers.DocumentBuilderFactory;
076 import javax.xml.parsers.ParserConfigurationException;
077 import javax.xml.transform.OutputKeys;
078 import javax.xml.transform.Transformer;
079 import javax.xml.transform.TransformerFactory;
080 import javax.xml.transform.dom.DOMSource;
081 import javax.xml.transform.stream.StreamResult;
082
083 import org.w3c.dom.DOMException;
084 import org.w3c.dom.Document;
085 import org.w3c.dom.Element;
086
087
090 public abstract class PortletResponseImpl implements LiferayPortletResponse {
091
092 public static PortletResponseImpl getPortletResponseImpl(
093 PortletResponse portletResponse) {
094
095 while (!(portletResponse instanceof PortletResponseImpl)) {
096 if (portletResponse instanceof PortletResponseWrapper) {
097 PortletResponseWrapper portletResponseWrapper =
098 (PortletResponseWrapper)portletResponse;
099
100 portletResponse = portletResponseWrapper.getResponse();
101 }
102 else {
103 throw new RuntimeException(
104 "Unable to unwrap the portlet response from " +
105 portletResponse.getClass());
106 }
107 }
108
109 return (PortletResponseImpl)portletResponse;
110 }
111
112 @Override
113 public void addDateHeader(String name, long date) {
114 if (Validator.isNull(name)) {
115 throw new IllegalArgumentException();
116 }
117
118 Long[] values = (Long[])_headers.get(name);
119
120 if (values == null) {
121 setDateHeader(name, date);
122 }
123 else {
124 values = ArrayUtil.append(values, Long.valueOf(date));
125
126 _headers.put(name, values);
127 }
128 }
129
130 @Override
131 public void addHeader(String name, String value) {
132 if (Validator.isNull(name)) {
133 throw new IllegalArgumentException();
134 }
135
136 String[] values = (String[])_headers.get(name);
137
138 if (values == null) {
139 setHeader(name, value);
140 }
141 else {
142 values = ArrayUtil.append(values, value);
143
144 _headers.put(name, values);
145 }
146 }
147
148 @Override
149 public void addIntHeader(String name, int value) {
150 if (Validator.isNull(name)) {
151 throw new IllegalArgumentException();
152 }
153
154 Integer[] values = (Integer[])_headers.get(name);
155
156 if (values == null) {
157 setIntHeader(name, value);
158 }
159 else {
160 values = ArrayUtil.append(values, Integer.valueOf(value));
161
162 _headers.put(name, values);
163 }
164 }
165
166 @Override
167 public void addProperty(Cookie cookie) {
168 if (cookie == null) {
169 throw new IllegalArgumentException();
170 }
171
172 Cookie[] cookies = (Cookie[])_headers.get("cookies");
173
174 if (cookies == null) {
175 _headers.put("cookies", new Cookie[] {cookie});
176 }
177 else {
178 cookies = ArrayUtil.append(cookies, cookie);
179
180 _headers.put("cookies", cookies);
181 }
182 }
183
184 @Override
185 public void addProperty(String key, Element element) {
186 if (key == null) {
187 throw new IllegalArgumentException();
188 }
189
190 if (StringUtil.equalsIgnoreCase(
191 key, MimeResponse.MARKUP_HEAD_ELEMENT)) {
192
193 List<Element> values = _markupHeadElements.get(key);
194
195 if (values != null) {
196 if (element != null) {
197 values.add(element);
198 }
199 else {
200 _markupHeadElements.remove(key);
201 }
202 }
203 else {
204 if (element != null) {
205 values = new ArrayList<>();
206
207 values.add(element);
208
209 _markupHeadElements.put(key, values);
210 }
211 }
212 }
213 }
214
215 @Override
216 public void addProperty(String key, String value) {
217 if (Validator.isNull(key)) {
218 throw new IllegalArgumentException();
219 }
220
221 addHeader(key, value);
222 }
223
224 @Override
225 public PortletURL createActionURL() {
226 return createActionURL(_portletName);
227 }
228
229 @Override
230 public LiferayPortletURL createActionURL(String portletName) {
231 return createLiferayPortletURL(
232 portletName, PortletRequest.ACTION_PHASE);
233 }
234
235 @Override
236 public Element createElement(String tagName) throws DOMException {
237 if (_document == null) {
238 try {
239 DocumentBuilderFactory documentBuilderFactory =
240 SecureXMLFactoryProviderUtil.newDocumentBuilderFactory();
241
242 DocumentBuilder documentBuilder =
243 documentBuilderFactory.newDocumentBuilder();
244
245 _document = documentBuilder.newDocument();
246 }
247 catch (ParserConfigurationException pce) {
248 throw new DOMException(
249 DOMException.INVALID_STATE_ERR, pce.getMessage());
250 }
251 }
252
253 return _document.createElement(tagName);
254 }
255
256 @Override
257 public LiferayPortletURL createLiferayPortletURL(
258 long plid, String portletName, String lifecycle) {
259
260 return createLiferayPortletURL(plid, portletName, lifecycle, true);
261 }
262
263 @Override
264 public LiferayPortletURL createLiferayPortletURL(
265 long plid, String portletName, String lifecycle,
266 boolean includeLinkToLayoutUuid) {
267
268 return DoPrivilegedUtil.wrap(
269 new LiferayPortletURLPrivilegedAction(
270 plid, portletName, lifecycle, includeLinkToLayoutUuid));
271 }
272
273 @Override
274 public LiferayPortletURL createLiferayPortletURL(String lifecycle) {
275 return createLiferayPortletURL(_portletName, lifecycle);
276 }
277
278 @Override
279 public LiferayPortletURL createLiferayPortletURL(
280 String portletName, String lifecycle) {
281
282 return createLiferayPortletURL(_plid, portletName, lifecycle);
283 }
284
285 @Override
286 public PortletURL createRenderURL() {
287 return createRenderURL(_portletName);
288 }
289
290 @Override
291 public LiferayPortletURL createRenderURL(String portletName) {
292 return createLiferayPortletURL(
293 portletName, PortletRequest.RENDER_PHASE);
294 }
295
296 @Override
297 public ResourceURL createResourceURL() {
298 return createResourceURL(_portletName);
299 }
300
301 @Override
302 public LiferayPortletURL createResourceURL(String portletName) {
303 return createLiferayPortletURL(
304 portletName, PortletRequest.RESOURCE_PHASE);
305 }
306
307 @Override
308 public String encodeURL(String path) {
309 if ((path == null) ||
310 (!path.startsWith("#") && !path.startsWith("/") &&
311 !path.contains(":
312
313
314
315 throw new IllegalArgumentException(
316 "URL path must start with a '/' or include ':
317 }
318
319 if (_urlEncoder != null) {
320 return _urlEncoder.encodeURL(_response, path);
321 }
322 else {
323 return path;
324 }
325 }
326
327 public long getCompanyId() {
328 return _companyId;
329 }
330
331 public HttpServletRequest getHttpServletRequest() {
332 return _portletRequestImpl.getHttpServletRequest();
333 }
334
335 @Override
336 public HttpServletResponse getHttpServletResponse() {
337 return _response;
338 }
339
340 public abstract String getLifecycle();
341
342 @Override
343 public String getNamespace() {
344 if (_wsrp) {
345 return "wsrp_rewrite_";
346 }
347
348 if (_namespace == null) {
349 _namespace = PortalUtil.getPortletNamespace(_portletName);
350 }
351
352 return _namespace;
353 }
354
355 public long getPlid() {
356 return _plid;
357 }
358
359 @Override
360 public Portlet getPortlet() {
361 if (_portlet == null) {
362 try {
363 _portlet = PortletLocalServiceUtil.getPortletById(
364 _companyId, _portletName);
365 }
366 catch (Exception e) {
367 _log.error(e);
368 }
369 }
370
371 return _portlet;
372 }
373
374 public String getPortletName() {
375 return _portletName;
376 }
377
378 public PortletRequestImpl getPortletRequest() {
379 return _portletRequestImpl;
380 }
381
382 @Override
383 public Map<String, String[]> getProperties() {
384 Map<String, String[]> properties = new LinkedHashMap<>();
385
386 for (Map.Entry<String, Object> entry : _headers.entrySet()) {
387 String name = entry.getKey();
388 Object[] values = (Object[])entry.getValue();
389
390 String[] valuesString = new String[values.length];
391
392 for (int i = 0; i < values.length; i++) {
393 valuesString[i] = values[i].toString();
394 }
395
396 properties.put(name, valuesString);
397 }
398
399 return properties;
400 }
401
402 public URLEncoder getUrlEncoder() {
403 return _urlEncoder;
404 }
405
406 @Override
407 public void setDateHeader(String name, long date) {
408 if (Validator.isNull(name)) {
409 throw new IllegalArgumentException();
410 }
411
412 if (date <= 0) {
413 _headers.remove(name);
414 }
415 else {
416 _headers.put(name, new Long[] {Long.valueOf(date)});
417 }
418 }
419
420 @Override
421 public void setHeader(String name, String value) {
422 if (Validator.isNull(name)) {
423 throw new IllegalArgumentException();
424 }
425
426 if (Validator.isNull(value)) {
427 _headers.remove(name);
428 }
429 else {
430 _headers.put(name, new String[] {value});
431 }
432 }
433
434 @Override
435 public void setIntHeader(String name, int value) {
436 if (Validator.isNull(name)) {
437 throw new IllegalArgumentException();
438 }
439
440 if (value <= 0) {
441 _headers.remove(name);
442 }
443 else {
444 _headers.put(name, new Integer[] {Integer.valueOf(value)});
445 }
446 }
447
448 public void setPlid(long plid) {
449 _plid = plid;
450
451 if (_plid <= 0) {
452 Layout layout = (Layout)_portletRequestImpl.getAttribute(
453 WebKeys.LAYOUT);
454
455 if (layout != null) {
456 _plid = layout.getPlid();
457 }
458 }
459 }
460
461 @Override
462 public void setProperty(String key, String value) {
463 if (key == null) {
464 throw new IllegalArgumentException();
465 }
466
467 setHeader(key, value);
468 }
469
470 public void setURLEncoder(URLEncoder urlEncoder) {
471 _urlEncoder = urlEncoder;
472 }
473
474 public void transferHeaders(HttpServletResponse response) {
475 for (Map.Entry<String, Object> entry : _headers.entrySet()) {
476 String name = entry.getKey();
477 Object values = entry.getValue();
478
479 if (values instanceof Integer[]) {
480 Integer[] intValues = (Integer[])values;
481
482 for (int value : intValues) {
483 if (response.containsHeader(name)) {
484 response.addIntHeader(name, value);
485 }
486 else {
487 response.setIntHeader(name, value);
488 }
489 }
490 }
491 else if (values instanceof Long[]) {
492 Long[] dateValues = (Long[])values;
493
494 for (long value : dateValues) {
495 if (response.containsHeader(name)) {
496 response.addDateHeader(name, value);
497 }
498 else {
499 response.setDateHeader(name, value);
500 }
501 }
502 }
503 else if (values instanceof String[]) {
504 String[] stringValues = (String[])values;
505
506 for (String value : stringValues) {
507 if (response.containsHeader(name)) {
508 response.addHeader(name, value);
509 }
510 else {
511 response.setHeader(name, value);
512 }
513 }
514 }
515 else if (values instanceof Cookie[]) {
516 Cookie[] cookies = (Cookie[])values;
517
518 for (Cookie cookie : cookies) {
519 response.addCookie(cookie);
520 }
521 }
522 }
523 }
524
525 @Override
526 public void transferMarkupHeadElements() {
527 List<Element> elements = _markupHeadElements.get(
528 MimeResponse.MARKUP_HEAD_ELEMENT);
529
530 if ((elements == null) || elements.isEmpty()) {
531 return;
532 }
533
534 HttpServletRequest request = getHttpServletRequest();
535
536 List<String> markupHeadElements = (List<String>)request.getAttribute(
537 MimeResponse.MARKUP_HEAD_ELEMENT);
538
539 if (markupHeadElements == null) {
540 markupHeadElements = new ArrayList<>();
541
542 request.setAttribute(
543 MimeResponse.MARKUP_HEAD_ELEMENT, markupHeadElements);
544 }
545
546 for (Element element : elements) {
547 try {
548 Writer writer = new UnsyncStringWriter();
549
550 TransformerFactory transformerFactory =
551 TransformerFactory.newInstance();
552
553 Transformer transformer = transformerFactory.newTransformer();
554
555 transformer.setOutputProperty(
556 OutputKeys.OMIT_XML_DECLARATION, "yes");
557
558 transformer.transform(
559 new DOMSource(element), new StreamResult(writer));
560
561 markupHeadElements.add(writer.toString());
562 }
563 catch (Exception e) {
564 if (_log.isWarnEnabled()) {
565 _log.warn(e, e);
566 }
567 }
568 }
569 }
570
571 protected LiferayPortletURL doCreateLiferayPortletURL(
572 long plid, String portletName, String lifecycle,
573 boolean includeLinkToLayoutUuid) {
574
575 try {
576 Layout layout = (Layout)_portletRequestImpl.getAttribute(
577 WebKeys.LAYOUT);
578
579 if (layout == null) {
580 ThemeDisplay themeDisplay =
581 (ThemeDisplay)_portletRequestImpl.getAttribute(
582 WebKeys.THEME_DISPLAY);
583
584 if (themeDisplay != null) {
585 layout = themeDisplay.getLayout();
586 }
587 }
588
589 if (_portletSetup == null) {
590 _portletSetup =
591 PortletPreferencesFactoryUtil.getStrictLayoutPortletSetup(
592 layout, _portletName);
593 }
594
595 String linkToLayoutUuid = GetterUtil.getString(
596 _portletSetup.getValue("portletSetupLinkToLayoutUuid", null));
597
598 if (PropsValues.PORTLET_CROSS_LAYOUT_INVOCATION_MODE.equals(
599 "render") &&
600 !PortletRequest.RENDER_PHASE.equals(lifecycle)) {
601
602 includeLinkToLayoutUuid = false;
603 }
604
605 if (Validator.isNotNull(linkToLayoutUuid) &&
606 includeLinkToLayoutUuid) {
607
608 try {
609 Layout linkedLayout =
610 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
611 linkToLayoutUuid, layout.getGroupId(),
612 layout.isPrivateLayout());
613
614 plid = linkedLayout.getPlid();
615 }
616 catch (PortalException pe) {
617 }
618 }
619 }
620 catch (SystemException se) {
621 if (_log.isWarnEnabled()) {
622 _log.warn(se);
623 }
624 }
625
626 if (plid == LayoutConstants.DEFAULT_PLID) {
627 plid = _plid;
628 }
629
630 PortletURLImpl portletURLImpl = null;
631
632 Portlet portlet = getPortlet();
633
634 String portletURLClass = portlet.getPortletURLClass();
635
636 if (portlet.getPortletId().equals(portletName) &&
637 Validator.isNotNull(portletURLClass)) {
638
639 if (portletURLClass.equals(
640 StrutsActionPortletURL.class.getName())) {
641
642 portletURLImpl = new StrutsActionPortletURL(
643 this, plid, lifecycle);
644 }
645 else {
646 try {
647 Constructor<? extends PortletURLImpl> constructor =
648 _constructors.get(portletURLClass);
649
650 if (constructor == null) {
651 Class<?> portletURLClassObj = Class.forName(
652 portletURLClass);
653
654 constructor =
655 (Constructor<? extends PortletURLImpl>)
656 portletURLClassObj.getConstructor(
657 new Class[] {
658 PortletResponseImpl.class, long.class,
659 String.class
660 });
661
662 _constructors.put(portletURLClass, constructor);
663 }
664
665 portletURLImpl = constructor.newInstance(
666 new Object[] {this, plid, lifecycle});
667 }
668 catch (Exception e) {
669 _log.error(e);
670 }
671 }
672 }
673
674 if (portletURLImpl == null) {
675 portletURLImpl = new PortletURLImpl(
676 _portletRequestImpl, portletName, plid, lifecycle);
677 }
678
679 PortletApp portletApp = portlet.getPortletApp();
680
681 Set<PortletURLListener> portletURLListeners =
682 portletApp.getPortletURLListeners();
683
684 for (PortletURLListener portletURLListener : portletURLListeners) {
685 try {
686 PortletURLGenerationListener portletURLGenerationListener =
687 PortletURLListenerFactory.create(portletURLListener);
688
689 if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
690 portletURLGenerationListener.filterActionURL(
691 portletURLImpl);
692 }
693 else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
694 portletURLGenerationListener.filterRenderURL(
695 portletURLImpl);
696 }
697 else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
698 portletURLGenerationListener.filterResourceURL(
699 portletURLImpl);
700 }
701 }
702 catch (PortletException pe) {
703 _log.error(pe, pe);
704 }
705 }
706
707 try {
708 portletURLImpl.setWindowState(_portletRequestImpl.getWindowState());
709 }
710 catch (WindowStateException wse) {
711 _log.error(wse.getMessage());
712 }
713
714 try {
715 portletURLImpl.setPortletMode(_portletRequestImpl.getPortletMode());
716 }
717 catch (PortletModeException pme) {
718 _log.error(pme.getMessage());
719 }
720
721 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
722 portletURLImpl.setCopyCurrentRenderParameters(true);
723 }
724
725 return portletURLImpl;
726 }
727
728 protected void init(
729 PortletRequestImpl portletRequestImpl, HttpServletResponse response,
730 String portletName, long companyId, long plid) {
731
732 _portletRequestImpl = portletRequestImpl;
733 _response = response;
734 _portletName = portletName;
735 _companyId = companyId;
736 _wsrp = ParamUtil.getBoolean(getHttpServletRequest(), "wsrp");
737
738 setPlid(plid);
739 }
740
741 private static final Log _log = LogFactoryUtil.getLog(
742 PortletResponseImpl.class);
743
744 private long _companyId;
745 private final Map<String, Constructor<? extends PortletURLImpl>>
746 _constructors = new ConcurrentHashMap<>();
747 private Document _document;
748 private final Map<String, Object> _headers = new LinkedHashMap<>();
749 private final Map<String, List<Element>> _markupHeadElements =
750 new LinkedHashMap<>();
751 private String _namespace;
752 private long _plid;
753 private Portlet _portlet;
754 private String _portletName;
755 private PortletRequestImpl _portletRequestImpl;
756 private PortletPreferences _portletSetup;
757 private HttpServletResponse _response;
758 private URLEncoder _urlEncoder;
759 private boolean _wsrp;
760
761 private class LiferayPortletURLPrivilegedAction
762 implements PrivilegedAction<LiferayPortletURL> {
763
764 public LiferayPortletURLPrivilegedAction(
765 long plid, String portletName, String lifecycle,
766 boolean includeLinkToLayoutUuid) {
767
768 _plid = plid;
769 _portletName = portletName;
770 _lifecycle = lifecycle;
771 _includeLinkToLayoutUuid = includeLinkToLayoutUuid;
772 }
773
774 @Override
775 public LiferayPortletURL run() {
776 return doCreateLiferayPortletURL(
777 _plid, _portletName, _lifecycle, _includeLinkToLayoutUuid);
778 }
779
780 private final boolean _includeLinkToLayoutUuid;
781 private final String _lifecycle;
782 private long _plid;
783 private String _portletName;
784
785 }
786
787 }