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