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