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