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