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