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