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.model.Layout;
031 import com.liferay.portal.model.LayoutConstants;
032 import com.liferay.portal.model.Portlet;
033 import com.liferay.portal.model.PortletApp;
034 import com.liferay.portal.model.PortletURLListener;
035 import com.liferay.portal.security.lang.DoPrivilegedUtil;
036 import com.liferay.portal.security.xml.SecureXMLFactoryProviderUtil;
037 import com.liferay.portal.service.LayoutLocalServiceUtil;
038 import com.liferay.portal.service.PortletLocalServiceUtil;
039 import com.liferay.portal.struts.StrutsActionPortletURL;
040 import com.liferay.portal.theme.ThemeDisplay;
041 import com.liferay.portal.util.PortalUtil;
042 import com.liferay.portal.util.PropsValues;
043 import com.liferay.portal.util.WebKeys;
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, new Long(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, new Integer(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<Element>();
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 public Portlet getPortlet() {
360 if (_portlet == null) {
361 try {
362 _portlet = PortletLocalServiceUtil.getPortletById(
363 _companyId, _portletName);
364 }
365 catch (Exception e) {
366 _log.error(e);
367 }
368 }
369
370 return _portlet;
371 }
372
373 public String getPortletName() {
374 return _portletName;
375 }
376
377 public PortletRequestImpl getPortletRequest() {
378 return _portletRequestImpl;
379 }
380
381 @Override
382 public Map<String, String[]> getProperties() {
383 Map<String, String[]> properties =
384 new LinkedHashMap<String, String[]>();
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[] {new Long(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[] {new Integer(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<String>();
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 = (Constructor<? extends PortletURLImpl>)
655 portletURLClassObj.getConstructor(
656 new Class[] {
657 PortletResponseImpl.class, long.class,
658 String.class
659 });
660
661 _constructors.put(portletURLClass, constructor);
662 }
663
664 portletURLImpl = constructor.newInstance(
665 new Object[] {this, plid, lifecycle});
666 }
667 catch (Exception e) {
668 _log.error(e);
669 }
670 }
671 }
672
673 if (portletURLImpl == null) {
674 portletURLImpl = new PortletURLImpl(
675 _portletRequestImpl, portletName, plid, lifecycle);
676 }
677
678 PortletApp portletApp = portlet.getPortletApp();
679
680 Set<PortletURLListener> portletURLListeners =
681 portletApp.getPortletURLListeners();
682
683 for (PortletURLListener portletURLListener : portletURLListeners) {
684 try {
685 PortletURLGenerationListener portletURLGenerationListener =
686 PortletURLListenerFactory.create(portletURLListener);
687
688 if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
689 portletURLGenerationListener.filterActionURL(
690 portletURLImpl);
691 }
692 else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
693 portletURLGenerationListener.filterRenderURL(
694 portletURLImpl);
695 }
696 else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
697 portletURLGenerationListener.filterResourceURL(
698 portletURLImpl);
699 }
700 }
701 catch (PortletException pe) {
702 _log.error(pe, pe);
703 }
704 }
705
706 try {
707 portletURLImpl.setWindowState(_portletRequestImpl.getWindowState());
708 }
709 catch (WindowStateException wse) {
710 _log.error(wse.getMessage());
711 }
712
713 try {
714 portletURLImpl.setPortletMode(_portletRequestImpl.getPortletMode());
715 }
716 catch (PortletModeException pme) {
717 _log.error(pme.getMessage());
718 }
719
720 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
721 portletURLImpl.setCopyCurrentRenderParameters(true);
722 }
723
724 return portletURLImpl;
725 }
726
727 protected void init(
728 PortletRequestImpl portletRequestImpl, HttpServletResponse response,
729 String portletName, long companyId, long plid) {
730
731 _portletRequestImpl = portletRequestImpl;
732 _response = response;
733 _portletName = portletName;
734 _companyId = companyId;
735 _wsrp = ParamUtil.getBoolean(getHttpServletRequest(), "wsrp");
736
737 setPlid(plid);
738 }
739
740 private static Log _log = LogFactoryUtil.getLog(PortletResponseImpl.class);
741
742 private long _companyId;
743 private Map<String, Constructor<? extends PortletURLImpl>> _constructors =
744 new ConcurrentHashMap<String, Constructor<? extends PortletURLImpl>>();
745 private Document _document;
746 private Map<String, Object> _headers = new LinkedHashMap<String, Object>();
747 private Map<String, List<Element>> _markupHeadElements =
748 new LinkedHashMap<String, List<Element>>();
749 private String _namespace;
750 private long _plid;
751 private Portlet _portlet;
752 private String _portletName;
753 private PortletRequestImpl _portletRequestImpl;
754 private PortletPreferences _portletSetup;
755 private HttpServletResponse _response;
756 private URLEncoder _urlEncoder;
757 private boolean _wsrp;
758
759 private class LiferayPortletURLPrivilegedAction
760 implements PrivilegedAction<LiferayPortletURL> {
761
762 public LiferayPortletURLPrivilegedAction(
763 long plid, String portletName, String lifecycle,
764 boolean includeLinkToLayoutUuid) {
765
766 _plid = plid;
767 _portletName = portletName;
768 _lifecycle = lifecycle;
769 _includeLinkToLayoutUuid = includeLinkToLayoutUuid;
770 }
771
772 @Override
773 public LiferayPortletURL run() {
774 return doCreateLiferayPortletURL(
775 _plid, _portletName, _lifecycle, _includeLinkToLayoutUuid);
776 }
777
778 private boolean _includeLinkToLayoutUuid;
779 private String _lifecycle;
780 private long _plid;
781 private String _portletName;
782
783 }
784
785 }