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