1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet;
16  
17  import com.liferay.portal.kernel.exception.PortalException;
18  import com.liferay.portal.kernel.exception.SystemException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
22  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
23  import com.liferay.portal.kernel.servlet.URLEncoder;
24  import com.liferay.portal.kernel.util.ArrayUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.ParamUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.model.Layout;
29  import com.liferay.portal.model.LayoutConstants;
30  import com.liferay.portal.model.Portlet;
31  import com.liferay.portal.model.PortletApp;
32  import com.liferay.portal.model.PortletURLListener;
33  import com.liferay.portal.service.LayoutLocalServiceUtil;
34  import com.liferay.portal.service.PortletLocalServiceUtil;
35  import com.liferay.portal.util.PortalUtil;
36  import com.liferay.portal.util.WebKeys;
37  
38  import java.lang.reflect.Constructor;
39  import java.lang.reflect.Method;
40  
41  import java.util.LinkedHashMap;
42  import java.util.Map;
43  import java.util.Set;
44  
45  import javax.portlet.PortletException;
46  import javax.portlet.PortletModeException;
47  import javax.portlet.PortletPreferences;
48  import javax.portlet.PortletRequest;
49  import javax.portlet.PortletResponse;
50  import javax.portlet.PortletURL;
51  import javax.portlet.PortletURLGenerationListener;
52  import javax.portlet.ResourceURL;
53  import javax.portlet.WindowStateException;
54  
55  import javax.servlet.http.Cookie;
56  import javax.servlet.http.HttpServletRequest;
57  import javax.servlet.http.HttpServletResponse;
58  
59  import org.w3c.dom.DOMException;
60  import org.w3c.dom.Element;
61  
62  /**
63   * <a href="PortletResponseImpl.java.html"><b><i>View Source</i></b></a>
64   *
65   * @author Brian Wing Shun Chan
66   */
67  public abstract class PortletResponseImpl implements LiferayPortletResponse {
68  
69      public static PortletResponseImpl getPortletResponseImpl(
70          PortletResponse portletResponse) {
71  
72          PortletResponseImpl portletResponseImpl = null;
73  
74          if (portletResponse instanceof PortletResponseImpl) {
75              portletResponseImpl = (PortletResponseImpl)portletResponse;
76          }
77          else {
78  
79              // LEP-4033
80  
81              try {
82                  Method method = portletResponse.getClass().getMethod(
83                      "getResponse");
84  
85                  Object obj = method.invoke(portletResponse, (Object[])null);
86  
87                  portletResponseImpl = getPortletResponseImpl(
88                      (PortletResponse)obj);
89              }
90              catch (Exception e) {
91                  throw new RuntimeException(
92                      "Unable to get the HTTP servlet resuest from " +
93                          portletResponse.getClass().getName());
94              }
95          }
96  
97          return portletResponseImpl;
98      }
99  
100     public void addDateHeader(String name, long date) {
101         if (Validator.isNull(name)) {
102             throw new IllegalArgumentException();
103         }
104 
105         if (_headers.containsKey(name)) {
106             Long[] values = (Long[])_headers.get(name);
107 
108             values = ArrayUtil.append(values, new Long(date));
109 
110             _headers.put(name, values);
111         }
112         else {
113             setDateHeader(name, date);
114         }
115     }
116 
117     public void addHeader(String name, String value) {
118         if (Validator.isNull(name)) {
119             throw new IllegalArgumentException();
120         }
121 
122         if (_headers.containsKey(name)) {
123             String[] values = (String[])_headers.get(name);
124 
125             values = ArrayUtil.append(values, value);
126 
127             _headers.put(name, values);
128         }
129         else {
130             setHeader(name, value);
131         }
132     }
133 
134     public void addIntHeader(String name, int value) {
135         if (Validator.isNull(name)) {
136             throw new IllegalArgumentException();
137         }
138 
139         if (_headers.containsKey(name)) {
140             Integer[] values = (Integer[])_headers.get(name);
141 
142             values = ArrayUtil.append(values, new Integer(value));
143 
144             _headers.put(name, values);
145         }
146         else {
147             setIntHeader(name, value);
148         }
149     }
150 
151     public void addProperty(Cookie cookie) {
152         if (Validator.isNull(cookie)) {
153             throw new IllegalArgumentException();
154         }
155 
156         if (_headers.containsKey("cookies")) {
157             Cookie[] cookies = (Cookie[])_headers.get("cookies");
158 
159             cookies = (Cookie[])ArrayUtil.append(cookies, cookie);
160 
161             _headers.put("cookies", cookies);
162         }
163         else {
164             Cookie[] cookies = new Cookie[] {cookie};
165 
166             _headers.put("cookies", cookies);
167         }
168     }
169 
170     public void addProperty(String key, Element element) {
171         if (key == null) {
172             throw new IllegalArgumentException();
173         }
174     }
175 
176     public void addProperty(String key, String value) {
177         if (Validator.isNull(key)) {
178             throw new IllegalArgumentException();
179         }
180 
181         addHeader(key, value);
182     }
183 
184     public PortletURL createActionURL() {
185         return createActionURL(_portletName);
186     }
187 
188     public LiferayPortletURL createActionURL(String portletName) {
189         return createLiferayPortletURL(
190             portletName, PortletRequest.ACTION_PHASE);
191     }
192 
193     public Element createElement(String tagName) throws DOMException {
194         return null;
195     }
196 
197     public LiferayPortletURL createLiferayPortletURL(String lifecycle) {
198         return createLiferayPortletURL(_portletName, lifecycle);
199     }
200 
201     public LiferayPortletURL createLiferayPortletURL(
202         String portletName, String lifecycle) {
203 
204         return createLiferayPortletURL(_plid, portletName, lifecycle);
205     }
206 
207     public LiferayPortletURL createLiferayPortletURL(
208         long plid, String portletName, String lifecycle) {
209 
210         try {
211             Layout layout = (Layout)_portletRequestImpl.getAttribute(
212                 WebKeys.LAYOUT);
213 
214             PortletPreferences portletSetup =
215                 PortletPreferencesFactoryUtil.getLayoutPortletSetup(
216                     layout, _portletName);
217 
218             long layoutId = GetterUtil.getLong(portletSetup.getValue(
219                 "portlet-setup-link-to-layout-id", null));
220 
221             if (layoutId > 0) {
222                 try {
223                     Layout linkedLayout = LayoutLocalServiceUtil.getLayout(
224                         layout.getGroupId(), layout.isPrivateLayout(),
225                         layoutId);
226 
227                     plid = linkedLayout.getPlid();
228                 }
229                 catch (PortalException pe) {
230                 }
231             }
232             else {
233 
234                 // Backwards compatibility
235 
236                 plid = GetterUtil.getLong(portletSetup.getValue(
237                     "portlet-setup-link-to-plid", String.valueOf(plid)));
238             }
239         }
240         catch (SystemException e) {
241             if (_log.isWarnEnabled()) {
242                 _log.warn(e);
243             }
244         }
245 
246         if (plid == LayoutConstants.DEFAULT_PLID) {
247             plid = _plid;
248         }
249 
250         PortletURLImpl portletURLImpl = null;
251 
252         Portlet portlet = getPortlet();
253 
254         String portletURLClass = portlet.getPortletURLClass();
255 
256         if (portlet.getPortletId().equals(portletName) &&
257             Validator.isNotNull(portletURLClass)) {
258 
259             try {
260                 Class<?> portletURLClassObj = Class.forName(portletURLClass);
261 
262                 Constructor<?> constructor = portletURLClassObj.getConstructor(
263                     new Class[] {
264                         com.liferay.portlet.PortletResponseImpl.class,
265                         long.class, String.class
266                     });
267 
268                 portletURLImpl = (PortletURLImpl)constructor.newInstance(
269                     new Object[] {this, plid, lifecycle});
270             }
271             catch (Exception e) {
272                 _log.error(e);
273             }
274         }
275 
276         if (portletURLImpl == null) {
277             portletURLImpl = new PortletURLImpl(
278                 _portletRequestImpl, portletName, plid, lifecycle);
279         }
280 
281         PortletApp portletApp = portlet.getPortletApp();
282 
283         Set<PortletURLListener> portletURLListeners =
284             portletApp.getPortletURLListeners();
285 
286         for (PortletURLListener portletURLListener : portletURLListeners) {
287             try {
288                 PortletURLGenerationListener portletURLGenerationListener =
289                     PortletURLListenerFactory.create(portletURLListener);
290 
291                 if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
292                     portletURLGenerationListener.filterActionURL(
293                         portletURLImpl);
294                 }
295                 else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
296                     portletURLGenerationListener.filterRenderURL(
297                         portletURLImpl);
298                 }
299                 else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
300                     portletURLGenerationListener.filterResourceURL(
301                         portletURLImpl);
302                 }
303             }
304             catch (PortletException pe) {
305                 _log.error(pe, pe);
306             }
307         }
308 
309         try {
310             portletURLImpl.setWindowState(_portletRequestImpl.getWindowState());
311         }
312         catch (WindowStateException wse) {
313             _log.error(wse.getMessage());
314         }
315 
316         try {
317             portletURLImpl.setPortletMode(_portletRequestImpl.getPortletMode());
318         }
319         catch (PortletModeException pme) {
320             _log.error(pme.getMessage());
321         }
322 
323         if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
324             portletURLImpl.setCopyCurrentPublicRenderParameters(true);
325         }
326 
327         if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
328             portletURLImpl.setCopyCurrentPublicRenderParameters(true);
329             portletURLImpl.setCopyCurrentRenderParameters(true);
330         }
331 
332         return portletURLImpl;
333     }
334 
335     public PortletURL createRenderURL() {
336         return createRenderURL(_portletName);
337     }
338 
339     public LiferayPortletURL createRenderURL(String portletName) {
340         return createLiferayPortletURL(
341             portletName, PortletRequest.RENDER_PHASE);
342     }
343 
344     public ResourceURL createResourceURL() {
345         return createResourceURL(_portletName);
346     }
347 
348     public LiferayPortletURL createResourceURL(String portletName) {
349         return createLiferayPortletURL(
350             portletName, PortletRequest.RESOURCE_PHASE);
351     }
352 
353     public String encodeURL(String path) {
354         if ((path == null) ||
355             (!path.startsWith("#") && !path.startsWith("/") &&
356                 (path.indexOf("://") == -1))) {
357 
358             // Allow '#' as well to workaround a bug in Oracle ADF 10.1.3
359 
360             throw new IllegalArgumentException(
361                 "URL path must start with a '/' or include '://'");
362         }
363 
364         if (_urlEncoder != null) {
365             return _urlEncoder.encodeURL(_response, path);
366         }
367         else {
368             return path;
369         }
370     }
371 
372     public long getCompanyId() {
373         return _companyId;
374     }
375 
376     public HttpServletRequest getHttpServletRequest() {
377         return _portletRequestImpl.getHttpServletRequest();
378     }
379 
380     public HttpServletResponse getHttpServletResponse() {
381         return _response;
382     }
383 
384     public abstract String getLifecycle();
385 
386     public String getNamespace() {
387         if (_wsrp) {
388             return "wsrp_rewrite_";
389         }
390 
391         if (_namespace == null) {
392             _namespace = PortalUtil.getPortletNamespace(_portletName);
393         }
394 
395         return _namespace;
396     }
397 
398     public long getPlid() {
399         return _plid;
400     }
401 
402     public Portlet getPortlet() {
403         if (_portlet == null) {
404             try {
405                 _portlet = PortletLocalServiceUtil.getPortletById(
406                     _companyId, _portletName);
407             }
408             catch (Exception e) {
409                 _log.error(e);
410             }
411         }
412 
413         return _portlet;
414     }
415 
416     public String getPortletName() {
417         return _portletName;
418     }
419 
420     public PortletRequestImpl getPortletRequest() {
421         return _portletRequestImpl;
422     }
423 
424     public Map<String, String[]> getProperties() {
425         Map<String, String[]> properties =
426             new LinkedHashMap<String, String[]>();
427 
428         for (Map.Entry<String, Object> entry : _headers.entrySet()) {
429             String name = entry.getKey();
430             Object[] values = (Object[])entry.getValue();
431 
432             String[] valuesString = new String[values.length];
433 
434             for (int i = 0; i < values.length; i++) {
435                 valuesString[i] = values[i].toString();
436             }
437 
438             properties.put(name, valuesString);
439         }
440 
441         return properties;
442     }
443 
444     public URLEncoder getUrlEncoder() {
445         return _urlEncoder;
446     }
447 
448     public void setDateHeader(String name, long date) {
449         if (Validator.isNull(name)) {
450             throw new IllegalArgumentException();
451         }
452 
453         if (date <= 0) {
454             _headers.remove(name);
455         }
456         else {
457             _headers.put(name, new Long[] {new Long(date)});
458         }
459     }
460 
461     public void setHeader(String name, String value) {
462         if (Validator.isNull(name)) {
463             throw new IllegalArgumentException();
464         }
465 
466         if (Validator.isNull(value)) {
467             _headers.remove(name);
468         }
469         else {
470             _headers.put(name, new String[] {value});
471         }
472     }
473 
474     public void setIntHeader(String name, int value) {
475         if (Validator.isNull(name)) {
476             throw new IllegalArgumentException();
477         }
478 
479         if (value <= 0) {
480             _headers.remove(name);
481         }
482         else {
483             _headers.put(name, new Integer[] {new Integer(value)});
484         }
485     }
486 
487     public void setPlid(long plid) {
488         _plid = plid;
489 
490         if (_plid <= 0) {
491             Layout layout = (Layout)_portletRequestImpl.getAttribute(
492                 WebKeys.LAYOUT);
493 
494             if (layout != null) {
495                 _plid = layout.getPlid();
496             }
497         }
498     }
499 
500     public void setProperty(String key, String value) {
501         if (key == null) {
502             throw new IllegalArgumentException();
503         }
504 
505         setHeader(key, value);
506     }
507 
508     public void setURLEncoder(URLEncoder urlEncoder) {
509         _urlEncoder = urlEncoder;
510     }
511 
512     public void transferHeaders(HttpServletResponse response) {
513         for (Map.Entry<String, Object> entry : _headers.entrySet()) {
514             String name = entry.getKey();
515             Object values = entry.getValue();
516 
517             if (values instanceof Integer[]) {
518                 Integer[] intValues = (Integer[])values;
519 
520                 for (int value : intValues) {
521                     if (response.containsHeader(name)) {
522                         response.addIntHeader(name, value);
523                     }
524                     else {
525                         response.setIntHeader(name, value);
526                     }
527                 }
528             }
529             else if (values instanceof Long[]) {
530                 Long[] dateValues = (Long[])values;
531 
532                 for (long value : dateValues) {
533                     if (response.containsHeader(name)) {
534                         response.addDateHeader(name, value);
535                     }
536                     else {
537                         response.setDateHeader(name, value);
538                     }
539                 }
540             }
541             else if (values instanceof String[]) {
542                 String[] stringValues = (String[])values;
543 
544                 for (String value : stringValues) {
545                     if (response.containsHeader(name)) {
546                         response.addHeader(name, value);
547                     }
548                     else {
549                         response.setHeader(name, value);
550                     }
551                 }
552             }
553             else if (values instanceof Cookie[]) {
554                 Cookie[] cookies = (Cookie[])values;
555 
556                 for (Cookie cookie : cookies) {
557                     response.addCookie(cookie);
558                 }
559             }
560         }
561     }
562 
563     protected void init(
564         PortletRequestImpl portletRequestImpl, HttpServletResponse response,
565         String portletName, long companyId, long plid) {
566 
567         _portletRequestImpl = portletRequestImpl;
568         _response = response;
569         _portletName = portletName;
570         _companyId = companyId;
571         _wsrp = ParamUtil.getBoolean(getHttpServletRequest(), "wsrp");
572 
573         setPlid(plid);
574     }
575 
576     private static Log _log = LogFactoryUtil.getLog(PortletResponseImpl.class);
577 
578     private PortletRequestImpl _portletRequestImpl;
579     private HttpServletResponse _response;
580     private String _portletName;
581     private Portlet _portlet;
582     private String _namespace;
583     private long _companyId;
584     private long _plid;
585     private URLEncoder _urlEncoder;
586     private Map<String, Object> _headers = new LinkedHashMap<String, Object>();
587     private boolean _wsrp;
588 
589 }