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