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